adactl-1.17r3/0000755000175000017510000000000012621403304012272 5ustar rosenadalogadactl-1.17r3/HISTORY0000644000175000017510000011715312621403276013376 0ustar rosenadalog============= == V1.17r3 == ============= General: -------- Quote all fields in CSV(X) format Uniformize some error messages Locations now accept the form "not ", removed "nested" (same as "not library"). Handle anonymous access to subprograms in various rules (previously ignored) and other fixes related to anonymous access types. Support of aspects (especially for things that relied previously on pragmas) Changes to existing rules: -------------------------- Declarations: Subrule Anonymous_Subtype_Case considers case expressions (2012) Added rule variable Declarations.Limited_Initialization to manage handling of initialization of variables of a limited type. Entities: Added modifier "instance" to report only on instances of a generic. Exception_Propagation: Consider expressions in aspects (2012) Expressions: Handle calls in prefixed notation Improper_Initialization: Do not consider branches terminated by raise as non-initializing Instantiations Allow more "=" than necessary. Do not consider generic "in" formals corresponding to "=" in the rule specification. Local_Access: Handle case of co-extensions Max_Call_Depth: Added parameters to specify entities that are not to be analyzed. No_Operator_Usage: Separate controls for Signed/Unsigned integers With_Clauses: Add variable to consider names in use clauses. ============== == V1.16r12 == ============== Minor bug fix release. (fixes to tests and doc, small improvements to code) ============== == V1.16r11 == ============== General: Recompiled for Gnat GPL 2014 Now up to date with the description (some changes mentionned under 1.16r10 didn't actually make it to the released sources). Bug fixes: Mantis: 0000038 ============== == V1.16r10 == ============== General: -------- Added .txt format for user guide and programmer manual Changes to existing rules: -------------------------- No_Operator_Usage: added observed relational Style (Multiple_Elements): separated keywords from other subrules With_Clauses: Handle correctly case of with clauses required due to a use clause or pragma Elaborate for the same package in the context clauses. ============= == V1.16r9 == ============= (Specific release, not released publicly) General: -------- Bug fixes: Mantis: 0000035, 0000036 New rules: ---------- positional_associations (took over style (positional_association)) type_usage unit_pattern unsafe_elaboration Changes to existing rules: -------------------------- Array_Declarations: Slightly changed the syntax of the component subrule. Case_Statements: Added subrule values_if_others Declarations: Added subrules box_defaulted_formal_function, name_defaulted_formal_function, box_defaulted_formal_procedure, name_defaulted_formal_procedure, null_defaulted_formal_procedure, non_ravenscar_task, access_constrained_array_type, access_unconstrained_array_type, access_def_discriminated_type, access_nondef_discriminated_type, access_unknown_discriminated_type, access_formal_type, access_language_type, equality_operator Better placement of some messages Dependencies: Added subrules public_child, private_child Expressions: Added subrules in, not_in, static_membership, and_array, and_logical, and_binary, or_array, or_logical, or_binary, xor_array, xor_logical, xor_binary, upward_conversion, downward_conversion, extension_aggregate, extendable_aggregate, array_positional_others, array_named_others, unconverted_fixed_multiplying_op Subrule Mixed_Operators considers membership tests and short circuit forms Local_Hiding: Added modifiers Not_Identical_Renaming, Not_Different_Families Global_References: Added subrules read, written Multiple_Assignments: The rule has been renamed to "Assignments" Added subrule sliding. Added criterion total. Naming_Convention: Added specific patterns by object and functions type names and categories Added subrules regular_static_constant, regular_nonstatic_constant No_Operator_Usage Changed syntax Filtering on indexing in addition to logical operators Object declarations: Added subrule type. Parameter_Declarations: Added subrules tagged_parameters, class_wide_parameters. Added callables dispatching_function, dispatching_parameter Reduceable_Scope: Don't suggest moving declarations to a task specification Representation_Clauses: Added subrule no_bit_order_layout Statements: Added subrules named_exit, exit_plain_loop, simple_block, unnamed_simple_block, redispatching_call. Normalized behaviour of subrule exit. Style (Casing_Identifier, original): Check closing identifier, allow multiple casing options. Positional_Association: removed, now a subrule of Positional_Associations. Parameter_Order, Formal_Parameter_Order: modes are separated by "|". Multiple_Element: also checks proper presentation of "end", "for ... loop", etc. Use_Clauses Added subrules type, type_global, type_local. ============= == V1.15r5 == ============= General: -------- Arranged to not choke on Ada 2012 constructs. Account for [in] out parameters in functions Bug fixes: Mantis: 0000033, 0000034 Added -j option Added command "set ignore inverted" (invert disabling of messages). Added command "set timing global" (global timing over all "go" commands) Syntax of entities: added 'all to designate all attributes Option -D: added header comment with the command that generated the list New rules: ---------- aspects Generic_Aliasing Changes to existing rules: -------------------------- (Many places): Considered expression functions in addition to regular functions Declarations: Added null_procedure_body, null_procedure_declaration, expression_function, unknown_discriminant Dependencies: Added subrule with (dependency on indicated units). Expressions: Added subrules if, if_elsif, if_no_else, case, for_all, for_some Local_Hiding: Added exception patterns. Replaced Overloading_Short with a rule variable. Max_Nesting: Added subrules Generic, Separate, Task fixed level to really be the nesting level Max_Size: Added subrules Package_Spec, Package_Body, Procedure_Body, Function_Body, Protected_Spec, Protected_Body, Entry_Body, Task_Spec, Task_Body, Unit. Put messages at end of failing element. Multiple_Assignment: Consider subcomponents as assigned only if they meet (recursively) the criteria of the control. Naming_Convention: Do not recheck formal parameters in bodies if there is an explicit specification. Parameter_Declarations: Changed syntax to allow min/max to be specified either for all parameters or for parameters of a given mode. Parameter_Aliasing: Improved algorithm to reduce uncheckables due to dispatching calls Pragmas: Added modifier "multiple" Statements: Added subrule for_iterator_loop Added accept Style (Casing_Identifier, original): Check formal parameters in bodies if there is an explicit specification. Style (exposed_literal): Added optional "max" to value, allow in all declarations With_Clauses (Reduceable): Control with clauses that can be changed to private with (can be disabled with the variable Check_Private_With). Usage: Speed improvement ============= == V1.14r9 == ============= General: -------- Provide two distributions due to changes in ASIS. Bug fixes: Mantis: 0000019, 0000021, 0000022, 0000024, 0000025, 0000026, 0000027, 0000028, 0000030, 0000031, 0000032 Naming of entities: Added the syntax "all type'" Locations: Added "in_generic" to the locations used in rules declarations and instantiations Debug: with -d option, AdaCtl is aborted by Ctrl-C with a message telling where it is PFNI: print range for discrete/array types Source command: Sourced file is searched on the path given by ADACTL_PATH Framework: ---------- Added management of rule variables Changes to existing rules (new gnat only): ------------------------------------------ Statements: Added for_in_loop, for_of_loop Changes to existing rules: -------------------------- All (relevant) rules: Added support of null procedures Abnormal_Function_Return: no error when a branch is terminated by a call to a "No_Return" procedure. Allocators: Generalized to all type categories, added "not" and "anonymous" modifier. Allowed multiple specification of same entity with different modifiers Declarations: Added subrules protected_discriminant, task_discriminant Entities: Added location modifier Exception_Propagation Don't consider loop parameter specifications as declarations. Expressions: Added subrules array_range, array_non_static_range, underived_conversion Naming_Convention: Added rule variable Naming_Convention.Default_Case_Sensitivity Parameter_Aliasing: Don't report aliasing with an in parameter of a by-copy type. Statements: added For_In_Loop, For_Of_Loop Style (Exposed_Literal) Treat negative numbers as if they were literals ============= == V1.13r8 == ============= General: -------- Bug fixes: Mantis: 000001, 000003, 000004, 000006, 000007, 000008, 000009, 000011, 000013, 000014 Crash in Max_Call_Depth for the declaration of access to SP types Incorrect handling of names of formal parameters of generic formal subprograms (lead to incorrect messages in rule Improper_Initialization) Declarations: abstract limited private was not recognized as limited private Constraint_Error in Style(Expression_Litteral) when a litteral has the value of System.Max_Int Crash in Multiple_Assignments when records include an explicit null component Added Wide_Text_IO to potentially blocking operations Improved help (explain what the rule does before syntax). Rule names in -h option (or help command) are interpreted as regexp if they don't match exactly a rule name. Ignore remaining of line after blank in an indirect file Accepts Ada 2005 new constructs Modified following rules to account for extended return statements: abnormal_function_return, silent_exceptions, improper_initialization Extended full name image of entities to deal with the return object of extended return statements. Ptree now works in ada2005 mode New rules: ---------- Local_Access Changes to existing rules: -------------------------- Allocators New modifier: Inconsistent (allocator subtype and designated subtype don't match) Array_Declarations Added subrule Index Declarations Added subrules Abstract_Operator, Anonymous_Access_Component, Anonymous_Access_Constant, Anonymous_Access_Discriminant, Anonymous_Access_Parameter, Anonymous_Access_Variable, Interface_Type, Scalar_Variable, Ordinary_Record_Variable, Tagged_Private_Type, Tagged_Variable Improper_Initializations Added modifier "return", handle extended returns Naming_Convention Added filter Interface_Type Representation_Clauses Added modifier Global Return_Type Added subrules limited_class_wide, anonymous_access Statements Added subrule extended_return, exited_extended_return Subrule Function_Return considers extended return statements ============= == V1.12r4 == ============= General: -------- Recompiled executable versions for GNAT/GPL 2010. Bug fixes: In rule Improper_Initialization: bad handling of slices, extra message for out parameter of a separate body without explicit spec. Work-around for ASIS bug that resulted in String not appearing as packed for rule Record_Declarations (Component) with older versions of Gnat. Work-around for ASIS bug that crashed AdaControl for some deeply nested instantiations. ============= == V1.12r3 == ============= General: -------- Bug fixes: Crash with record components of an anonymous access type (Ada2005) Expression (Mixed_Operators) did not handle properly "abs" and "not" Local_Hiding claimed that formals of a separate body hid their counterpart from the spec. Compatibility: Made the code compatible to the new conditional expression feature (GNAT extension). Misc: Execution time is now reported as h mn s. GPS integration --------------- Better integration with GPR projects. Note that this requires copying the file GPS/adacontrol.xml into /share/gprconfig when installing AdaControl manually. Framework: ---------- Based numbers in rule parameters are now supported ".aru" extension taken by default for rules files. New rules: ---------- Record_Declarations Changes to existing rules: -------------------------- Array_Declarations Added subrule dimensions Barrier_Expressions No more fooled by renamings Declarations: Added subrules renaming_as_body, renaming_as_declaration Entity_Inside_Exception: Added entry_calls as parameter Expressions: Real_Equality: do not issue message for user defined "=". and, or, xor: now follow renamings Added subrules explicit_dereference, implicit_dereference, fixed_multiplying_op, inherited_function_call, Entity_Inside_Exception No more fooled by renamings Instantiations: No more fooled by renamings. Controls generics in generics. Object_Declarations: Added subrule address_not_volatile Representation_Clauses: Added modifier "object" to attribute specification Return_Type: Added subrule constrained_array Special_Comments: changed rule name to Comments. Added subrule position Statements: Added subrules entry_call, inherited_procedure_call ============= == V1.11r4 == ============= General: -------- Recompiled executable versions for GNAT/GPL 2009; some adjustments needed. Bug fixes: Simplifiable_Expressions (conversion) could report on conversions that were actually necessary due to the rules for fixed point multiply/divide Improper_Initialization considered use of variables in prefix of attributes as a read of the variable. Inhibit command ignored the "all" in the "all " syntax. Changes to commands: -------------------- set: added exit_on_error Changes to existing rules: -------------------------- Parameter_Aliasing Avoid issuing an Uncheckable message for dispatching calls when there is no more than one variable in the call (and with_in is not used). ============= == V1.11r3 == ============= General: -------- Bug fixes: Compilation unit pragmas were not processed. Representation_Clauses: Constraint_Error on null ranges for component clauses Style (Formal_Parameter_Order): not processed correctly if Default_In or Parameter_Order not given at the same time. Special_Comments (Pattern): treated "--" in string literals as comments GPS settings: value of units file is remembered in the switch dialog Improvements: Predefined and derived types have 'Size recognized by the static evaluator Block statements that contain only a null statement are considered as null statements for the rules dealing with null statements. pfni: If the identifier is initialized by a static expression (and especially a constant), the value is displayed after the full name. Changes to commands: -------------------- set: added new_output Changes to existing rules: -------------------------- Declarations: Added subrules constrained_array_constant, unconstrained_array_constant, instantiation, initialized_variable, non_joint_CE_NE_handler Max_Call_Depth: Better handling of dynamic calls or calls to SP whose body is missing or unknown. Report "at least" for indirect calls to these. Pragmas: If several controls apply to the same pragma, they are all reported instead of only the most specific one. Representation_clauses: Added categories to subrules Simpifiable_Expressions Conversion reports conversions of universal values Special_Comments Added subrule "terminating" ============== == V1.10r10 == ============== Minor bug fix release: - Problem following several levels of renaming in rule usage - Workaround for an ASIS bug involving renaming and generic child units ============= == V1.10r8 == ============= General: -------- Bug fixes: Missing handling of Name_Error when "set output" was given a bad file name. Due to a GPS bug, setting the "statistics" from the switches pannel generated an incorrect command line. Syntax: Exponent notation accepted for integer numbers. added commands set check_key|search_key Possibility to have several controls attached to the same label Environment: Default settings can be provided through environment variable ADACTLINI Statistics: if the output_format is none, statistics are output in CSVX format Messages: In verbose mode, added run number to message. Changes to commands: -------------------- message: added optional parameter "pause" Changes to existing rules: -------------------------- allocators bug fix: correct processing of class wide types in all cases if is part of a generic, covers all instances array_declarations ability to specify min and max values for subrule first. changed subrule max_length to length, with ability to specify min and max values. added subrules last, component declarations renamed subrules initialized_record_field, uninitialized_record_field, initialized_protected_field, uninitialized_protected_field, to initialized_record_component, uninitialized_record_component, initialized_protected_component, uninitialized_protected_component split subrule aliased into aliased_variable, aliased_constant added subrules aliased_array_component, aliased_record_component, aliased_protected_component, library_unit_renaming, protected_variable, self_calling_function, self_calling_procedure, task_variable directly_accessed_globals: better handling of renamed entities duplicate_initialization_calls better handling of renamed entities entities: better handling of renamed entities exception_propagation: bug fix: elaboration of subprograms were considered propagating function calls in named number declaration and scalar type declarations are no more considered as potentially propagating exceptions, since they are required by the language to be static. better handling of renamed entities. expressions: added subrules parameter_view_conversion, prefixed_operator. added categories to subrules type_conversion, parameter_view_conversion, prefixed_operator. global_references bug fix when using renamings. changed format of messages (variable name first) to make sorting easier when the result is loaded into a spreadsheet program. header_comments: added general repetition factors in patterns, and special repetitions "?" and "+". improper_initialization: added modifier "package", package variables no more checked by default mentionning a variable name in a representation clause is no more considered a usage of the variable the rule reported incorrectly for initializations and usages from nested program units. Packages are now processed correctly, other kinds of units are explicitely not analyzed. Better handling of renamed entities instantiations added to the specification of formal parameters. better handling of subtypes Bug fix: works with class-wide types local_hiding added modifier not_operator, not_enumeration added subrule overloading_short. movable_accept_statements better handling of renamed entities. reduceable_scope added modifier to_body representation_clauses: added subrules non_aligned_component, derived_record, extension_record, tagged_record style (no_closing_name): bug fix: do not issue message for tasks declared as "task T;". style (positional_association) added possibility of specifying exempted entities for "call", "instantiation", and "pragma" uncheckable a global count of "uncheckable" messages, and subtotals by rules, now appears in statistics. unsafe_paired_calls better handling of renamed entities usage better handling of renamed entities ============ == V1.9r4 == ============ General: -------- Bug fixes: A4G_Bugs.Corresponding_called_function blew up for "/=" functions obtained by instantiation. Scoped_Store not restoring spec context for subprograms. Memory leaks fixed. Bad defaults in "style" rule. CSV and CSVX format: file name, line, and column are now in three different columns. GPS: ---- Added "About" entry to Help/AdaControl menu New rules: ---------- dependencies Changes to existing rules: -------------------------- declarations added subrules anonymous_subtype_allocator, anonymous_subtype_case, anonymous_subtype_declaration, anonymous_subtype_for, anonymous_subtype_indexing, any_declaration, class_wide_constant, class_wide_variable, empty_visible_part, empty_private_part, function_call_renaming, ordinary_fixed_type_with_small, ordinary_fixed_type_no_small default_parameter can specify "calls" or "instantiations" (in addition to "all") as the first parameter. 3rd parameter: "not used" changed to "not_used", added "used_positional" exception_propagation added subrule local_exception expressions added subrules type_conversion, universal_range max_call_depth better caching of subprograms => significant speed-up not_elaboration_calls added "new" for allocators in addition to SP names object_declarations: added subrule volatile_no_address other_dependencies changed to subrule of dependencies representation_clauses added subrule overlay silent_exceptions added possibility to define which exceptions are controlled to the parameters. separated "raise" in "explicit_raise" and "reraise". simplifiable_statements added subrule loop_for_while special_comments old behaviour now under subrule pattern, added subrule unnamed_begin statements added subrules any_statement, exit_expanded_name, exit_outer_loop, raise_locally_handled, raise_nonpublic statements (raise) always reports, even if another "raise" subrule is also applicable. All "raise" subrules except the plain one also consider calls from procedures from Ada.Exceptions. style added subrule parameter_order usage added from_private and from_visible to the conditions, and "private" or "visible to the message. ============ == V1.8r8 == ============ Bug fix release: ---------------- Added back GPS interface from 1.7r9 in directory GPS-old, because GPS 4.2 is needed for the new interface, and not yet publicly available. Added missing files for "info" version of manuals ============ == V1.8r7 == ============ General: -------- New options -M and -m and corresponding commands ("set Max_Messages" and "set Max_Errors"). -T ("set Timing on"). Rearranged User Guide, clarified the notions of "rule", "control" and "command". New commands: ------------- set warning_as_error set timing help commands|license|options|rules|version GPS: ---- Now requires GPS > v4.2 Improved messages (better statistics in locations window) In interactive mode, check syntax before launching Adacontrol for good. Added menu "create units file" Added option to store result in file and reload in GPS. Added option to use .adp file Added option to set ASIS options Added preferences for -m and -M options Added preference to choose whether to display AdaControl command and result Changes to existing rules: -------------------------- abnormal_function_return accepts if and case statements, if all paths contain raise or return barrier_expressions fixed bug, some local protected function calls were not properly recognized case_statement allowed min/max values for all subrules declarations added subrules multiple_protected_entries, unconstrained_subtype, controlled_type, constrained_array_variable, unconstrained_array_variable, incomplete_type, deferred_constant, formal_type added location library expressions added subrules array_partial_others, record_partial_others header_comments (model) made repeated lines in pattern not greedy instantiations added location library max_parameters renamed to parameter_declarations, max_parameters now a subrule added subrule min_parameters, max_defaulted_parameters, single_out_parameter naming_convention added explicit rules for renamings. added "others" modifier. non_static added parameters index_check potentially_blocking_operations fixed bug that made some weird cases of internal calls appear as external calls reduceable_scope controls declarations from package specs that are not used outside the body simplifiable_expressions added logical_not simplifiable_statements added if_not statements added unnamed_for_loop, unnamed_simple_loop, unnamed_while_loop, if_elsif, effective_declare_block style (default_in): fixed bug: rule was triggered for access parameters style (exposed_literal): added places: index, exponent, pragma, type style (positional_parameter) added modifier "not_operator" for "call" usage added subrules: type, procedure, function, generic ============= == V1.7r13 == ============= (Specific release, not released publicly) General: -------- Bug fix: type_initial_value did not work for types declared in library package specs. Bug fix: improper handling of return and goto in rule improper_initialization Fixed documentation for rule Type_Initial_Values New rules: ---------- object_declarations ============= == V1.7r12 == ============= (Specific release, not released publicly) General: -------- Bug fix: fixed error in error recovery procedure ASIS bug workaround: failure in Name_Image (GNAT 6.0.x only) GPS: ---- Added "Load result file" to AdaControl menu New commands: ------------- set tag1 set tag2 Changes to existing rules: -------------------------- declarations added parameters: binary_modular_type, non_binary_modular_type, access_all_type, access_constant_type ============ == V1.7r9 == ============ General: -------- Bug fix: missing proper bodies not reported by uncheckable. New example rules file: reserved_2005.aru Added support for AdaGide Framework: ---------- String parameters now handled as a kind of parameter type, improved Matching_Context for operators => Default_Parameter (and others) now handle correctly operators Missing units are no more reported unless the -v option is given; use the rule "check uncheckable (missing_unit)" to make sure that there are no missing unit. Issue a header line when the output file is created with format CSV[X]. Added new output format "None". GPS: ---- Counts now appear under the "Counts summary" category in the locations window Bug fixes: AdaControl executed twice with "project" menu Do not process files that are not "ada" Added contextual menu to call pfni on the current entity Added parameters to auto-save files before running AdaControl Added icon to run AdaControl interactively on current file Preference to choose which units the buttons operate on PFNI: ----- Adjusted the result of profiles to match the syntax used in AdaControl. Added possibility to specify a unit as a file name. Added range of lines in unit specification Added -q option Made -FS the default ASIS option PTREE: ------ Added possibility to specify a unit as a file name. Added range of lines in unit specification Made -FS the default ASIS option New rules: ---------- duplicate_initialization_calls max_size multiple_assignments no_operator_usage not_selected_name simplifiable_statements type_initial_values (lacking documentation) units Changes to existing rules: -------------------------- control_characters renamed to characters (control). Added parameters trailing_space, not_iso_6464, wide. declarations changed parameters: nested_XXX to XXX added parameters: function, procedure, abstract_function, abstract_procedure, null_procedure, abstract_type, uninitialized_variable, character_literal, variant_part, variable, non_identical_operator_renaming, predefined_operator added location modifier removed limitation that the same keyword could not be used with different rule types default_parameter now handles default formal subprograms in generic instantiations can be applied to a parameter of a generic subprogram (checks all instantiations) expressions added parameters: inconsistent_attribute_dimension, array_aggregate, complex_parameter, mixed_operators, record_aggregate, unqualified_aggregate global_references recognize properly uncheckable cases added keywords function, procedure if_for_case changed into a subrule of simplifiable_statement insufficient_parameters processes membership test like other forms of expressions instantiations does not print a count of messages any more added location modifier added = to detect double instantiations local_hiding now works also with definitions of operators added parameters: strict (as before), overloading, both local_instantiation: removed (now covered by declarations and instantiations) no_safe_initialization renamed to improper_initialization added parameter initialized_variable and modifiers access/limited detection of use-before-assignment non_static added parameters variable_initialization, constant_initialization parameter_aliasing added modifier "with_in" potentially_blocking_operations recognize properly uncheckable cases reduceable_scope fixed false positives in some special cases now works also with definitions of operators added parameter to select what is controlled added support for use clauses representation_clauses added parameter: fractional_size, incomplete_record, non_contiguous_record simplifiable_expressions added parameter: conversion statements added parameter: declare_block moved parameters unnecessary_null and while_true to simplifiable_statements style added casing_keyword added "flexible" to multiple_elements (clause) uncheckable false positive messages are not printed if the corresponding rule is not triggered. unnecessary_use_clause tells cases where a use clause is given for a package which is always used with qualified names, or only for operators. added parameters to select the kind of use which is reported usage do not analyze instantiations of predefined or inhibited-all units diagnose uncheckable cases special processing for pseudo-constants use_clauses added global/local (optional) parameter ============ == V1.6r8 == ============ General: -------- Counters and statistics are in CSV format if CSV format requested Use a project file to build AdaControl Accept "~" as a string delimiter GPS: ---- It is now possible to pass quoted parameters interactively New rules: ---------- barrier_expressions Changes to existing rules: -------------------------- Declarations: added operator_renaming Entity_Inside_Exceptions: added calls, [not] Expressions: added array_others, record_others Naming_Convention: moved the location parameter. Added "unit" to locations. Positional_Parameter: changed name of rule to insufficient_parameters, removed first parameter ("maximum" now handled by style (positional_association)). Statements: added for_loop, simple_loop. in multiple_exits: now consider exits from nested exception handlers Style: changed casing to casing_identifier added compound_statement, casing_attribute, casing_pragma added allowable value to positional_association Uncheckable: added missing_unit ============ == V1.6r5 == ============ (Specific release, not released publicly) General: -------- Option to just list rules (-h list) Form of syntax/parameter messages made consistent with form of report messages GPS: ---- Rules menu for "Help/AdaControl/Help on rule" Choose "help on rule" style in preferences Added "Check rules file" and option to check form file/single rule in AdaControl menu Switches to output to file Possibility to redefine the command to run AdaControl through languages tab Preferences: check box to delete .ali files. New rules: ---------- Array_Declarations Expressions Max_Call_Depth Max_Parameters Other_Dependencies Uncheckable Unsafe_Unchecked_Conversion Changes to existing rules: -------------------------- case_statement added parameter: max_range_span changed parameters: min_others_range into min_others_span declarations: added parameters: in_out_parameter, out_parameter, initialized_record_field, limited_private_type, non_limited_private_type, private_extension, uninitialized_record_field, initialized_protected_field, uninitialized_protected_field, nested_package, nested_generic_function, nested_generic_package, nested_generic_procedure, nested_function_instantiation, nested_package_instantiation, nested_procedure_instantiation, non_identical_renaming changed parameters: formal_in_out => in_out_generic_parameter renames => renaming not_operator_renames => not_operator_renaming default_parameter: possibility to replace the and by "all" Fixed problem that prevented analysis of subprogram calls header_comments: added a parameter, possibility to provide a pattern file no_safe_initialization: now considers case and if statements non_static_constraints: changed name of rule to non_static added parameter instantiation real_operators: no more a rule of its own, now expressions(real_equality) max_statement_nesting: added parameter: block (also in "all") statements: added parameters: block, dispatching_call, labelled, null, reraise, unnamed_block, unnamed_loop_exited, unnecessary_null, while_loop style: added support for character and string literals. parameters added to "exposed_literal" subrule to specify the kind of literals and places parameters added to "multiple_elements" subrule to specify the kind of element split parameter "aggregate" for "positional_association" subrule in "array_aggregate" + "record_aggregate" added renamed_entity parameter unsafe_paired_calls: added possibility of having multiple opening/closing procedure for the same closing/opening one. ============= == V1.5r24 == ============= General: -------- Do no stop analysis of rules file at first error Option to just check syntax (-C) Option to specify a trace file (-t, set trace) Option to not print warnings (-E, set warnings on/off). Option to report statistics (-S, set statistics) Option to output result in various formats (-F, set format gnat/gnat_short/csv/csv_short/csvx/csvx_short/source/source_short) Improved processing of child units: parent context is properly restored. -v option displays progression indicator, tells units not found, does not print messages about controlling units that cannnot exist (SP bodies without specs, package specs that cannot have bodies) reports execution time. Less tree swapping in Local_Hiding, should result in sensible speed improvement Improved integration into GPS New rules: ---------- Abnormal_Function_Return Case_Statement Control_Characters Directly_Accessed_Globals Header_Comments If_For_Case Global_References Max_Blank_Lines Max_Line_Length Max_Statement_Nesting Movable_Accept_Statements No_Safe_Initialization Non_Static_Constraints Positional_Parameters Potentially_Blocking_Operations Reduceable_Scope Return_Type Special_Comments Style Terminating_Tasks Unsafe_Paired_Calls Usage With_Clauses Changes to existing rules: -------------------------- Allocators: Treat T'Class as T'Class, no more as T added task and protected Declarations: added parameters: access_protected_type, access_task_type, array, array_type, child_unit, constant, constrained_array_type, decimal_fixed_type, defaulted_discriminant, defaulted_generic_parameter, defaulted_parameter, derived_type, discriminant, enumeration_type, entry, extension, fixed_type, float_type, formal_function, formal_in_out, formal_package, formal_procedure, generic, handlers, integer_type, modular_type, multiple_names, named_number, not_operator_renames, null_extension, operator, null_ordinary_record_type, null_tagged_type, ordinary_fixed_type, ordinary_record_type, package_statements, protected, protected_entry, protected_type, renames, separate, signed_type, single_array, single_protected, single_task, subtype, tagged_type, task_entry, task_type, type, unconstrained_array_type changed parameters: access => access_type, access_subprogram => accept_subprogram_type Entities: Follows renamings and instantiations Exception_Propagation: added a level of checking to specify the possibility of exceptions being raised during the elaboration of declarative parts added "declaration" keyword Local_Instantiation: without parameter, all local instantiations are controlled Naming_Convention: added any|local|global modifier No_Closing_Name: no more a rule of its own, now a subrule of style Parameter_Aliasing: new algorithm, handles more static cases where there is no true aliasing Pragmas: allow "all" as parameter Silent_Exceptions: Bug fix when complicated exit in loops handle function calls and generic instantiations. More clever analysis of for loops Can specify "return" and "requeue" as non-silent actions Simplifiable_Expressions: All cases of unnecessary parentheses are now controlled. Specification_Objects The rule is now part of Usage (object, from_spec) Better treatment of references to objects through formals in-out from within instantiations Statement: Changed name to statements (with an "s", for consistency with other rules) Added parameters: Accept_Return, Asynchronous_Select, Case_Others_Null, Conditional_Entry_Call, Entry_Return, Exception_Others, Exception_Others_Null, Exit_For_Loop, Exit_While_Loop, Function_Return, Loop_Return, Multiple_Exits, No_Else, Procedure_Return, Raise_Standard, Selective_Accept, Timed_Entry_Call, Unconditional_Exit, Unnamed_Multiple_Loop, Untyped_For, While_True Unnecessary_Use: Bug fix works with use clauses coming from parent units When_Others_Null no more a rule of its own, now a subrule of statements Commands: --------- Inhibit: Added "all" for rule names, "all" for units Framework: ---------- Added boolean trace procedure Added support for "textual" rules Evaluator for static expressions and static ranges Support for float parameters, negative values for integer and float parameters ... and a few other utilities ============= == V1.4r20 == ============= Bug fix and speed improvement in rule Local_Hiding. ============= == V1.4r18 == ============= General: -------- Interactive mode. option "-f -" to read Standard_Input in non-interactive mode New commands: go, clear, quit, set, output, help, inhibit New rule type: count Support for attributes, and syntax "all '" Rule files no_standard_entity.aru, no_system_entity.aru and no_standard_unit.aru Small improvements, bug fixes... New rules: ---------- Declarations Exception_Propagation Naming_Convention Real_Operators Representation_Clauses Side_Effect_Parameters Simplifiable_Expressions Specification_Objects Statements When_Others_Null Changes to existing rules: -------------------------- Non_Raising_Non_Reporting_Exception_Handler: changed name to Silent_Exceptions Attributes: removed (Attributes are now processed by Entities) Parameter_Aliasing: Support for litteral expressions Framework: ---------- Added procedure Command + Finalize to all rules. Packages Framework.Plugs, Framework.Specific_Plugs New naming scheme for tests Improvements to the parameter parsing procedures Changed the processing of strings ("...") in the scanner. ============ == V1.3r2 == ============ Changed the name from AdaRC to AdaControl to avoid conflicts with RainCode's tool. ============ == V1.3r1 == ============ First public release (as AdaRC) adactl-1.17r3/doc/0000755000175000017510000000000012621403304013037 5ustar rosenadalogadactl-1.17r3/doc/adacontrol_ug.info-20000644000175000017510000041562712621403304016713 0ustar rosenadalogThis is adacontrol_ug.info, produced by makeinfo version 6.0 from adacontrol_ug.texi.  File: adacontrol_ug.info, Node: Reduceable_Scope, Next: Representation_Clauses, Prev: Record_Declarations, Up: Rules reference 5.46 Reduceable_Scope ===================== This rule controls declarations that could be moved to some inner scope. 5.46.1 Syntax ------------- reduceable_scope [( {, })]; ::= {} all | variable | constant | subprogram | type | package | exception | generic | use ::= no_blocks | to_body 5.46.2 Action ------------- The rule reports on any declaration that is referenced only from a single, inner scope, or in the case of 'use' clauses, it will report on packages named in a 'use' clause whose elements are used only in a single, inner scope. For entitities declared in package specifications, the rule reports if they are used only from the corresponding package body. The initialization of an object is considered a usage of the object at the place where it is declared, thus preventing it from being moved. Therefore, constants and initialized variables are never reported as being movable to inner scopes; they are reported as being movable to package bodies however. Entities that are used as prefixes of a 'Access or 'Address attribute are never reported, since moving them would change their accessibility level. Similarly, task objects are not reported since moving them would change their master. Finally, dispatching operations (primitive operations of tagged types) are not reported either, since they can be the target of an "invisible" (dispatching) call. If no is given, or the is "all", all declarations are controlled. If 'no_blocks' is specified in front of a , the rule will not consider blocks as possible targets for a reduced scope for the corresponding category. If 'to_body' is specified in front of a , the rule will report only elements declared in a package specification that could be moved into the body. Specifying "all" explicitely is only useful in the case where there is a . As a side effect, the rule will report about entities that are declared but not used (i.e. whose scope reduces to nothing). Ex: -- Types and variables shall be declared in the innermost scope -- where they are useful: check reduceable_scope (variable, type); -- Packages and subprograms shall be declared in the innermost -- scope where they are useful, but they are not allowed in blocks: check reduceable_scope (no_blocks subprogram, no_blocks package); -- Use clause should be as restricted as possible: search reduceable_scope (use); 5.46.3 Tips ----------- If you think that 'use' clauses are acceptable, but should be limited to the smallest possible scope, you would generally specify: check unnecessary_use_clause; check reduceable_scope (use); 5.46.4 Limitation ----------------- Currently, the rule does not report 'use' clauses declared in a package specification that could be moved to the body. Such clauses appear as "unused" (but of course, the compiler will complain on the body if the clause is removed).  File: adacontrol_ug.info, Node: Representation_Clauses, Next: Return_Type, Prev: Reduceable_Scope, Up: Rules reference 5.47 Representation_Clauses =========================== This rule controls usage of representation clause. 5.47.1 Syntax ------------- representation_clauses [( {, })]; ::= {} | [global] [object] ::= at | at_mod | enumeration | fractional_size | incomplete_layout | layout | non_aligned_component | non_contiguous_layout | no_bit_order_layout | overlay ::= () | range | mod | delta | digits | array | record | tagged | extension | access | new | private | task | protected 5.47.2 Action ------------- Without parameter, the rule controls all representation clauses, otherwise it will control the representation clauses given as parameter. If a representation keyword or attribute is preceded by one or several categories, the rule controls only the representation items that apply to types belonging to the categories (the type of the component for the 'non_aligned_component' subrule): * "()": Enumerated types * "range": Signed integer types * "mod": Modular types * "delta": Fixed point types (no possibility to differentiate ordinary and decimal fixed point types yet). * "digits": Floating point types * "array": Array types * "record": (untagged) record types * "tagged": Root tagged types * "extension": Type extensions (tagged derived types) * "access": Access types * "new": Derived types * "private": Private types * "task": Task types * "protected": Protected types The meaning of the representation keywords is: * "at" controls address clauses given in Ada 83 style ("for XXX use at"). * "at_mod" controls alignment clauses given in Ada 83 style ("for T use record at mod XX;"). * "enumeration" controls enumeration representation clauses. * "fractional_size" controls size clauses whose value is not an integral multiple of 'System.Storage_Unit'. * "incomplete_layout" controls record representation clauses that miss the specification of some components of the record's type. * "layout" controls all record representation clauses, while "no_bit_order_layout" controls record representation clauses whose type is not also the target of a bit_order attribute specification (such types have a non-portable representation). * "non_aligned_component" controls components that do not start on a storage unit boundary. The message gives the offset (in bits) relative to the closest storage unit boundary. * "non_contiguous_layout" controls record representation clauses where there are unused bits between components (or before the first component). A message is issued for each "gap" between components. In addition, if a size clause is given for the type, the rule will report if there are unused bits at the end of the component (i.e. the size clause is bigger than the end of the last component). In the case of variant records, there can be overlapping fields; the rule will control only the bits that belong to no variant at all. * "overlay" controls address clauses (given in either style), where the value given is the ''Address' of some other element. In addition to these keyword, any specifiable attribute can be given (including the initial "'''"); the rule will control specifications of this attribute. If the modifier "global" is given before the attribute, only attribute specifications for global entities are controlled. If the modifier "object" is given before the attribute, only attribute specifications for objects are controlled (as opposed to types for example). Note that double attributes (like "''CLASS'INPUT'") can be given, and are considered different from the simple attribute ("''INPUT'"). It is of course possible to specify both. Ex: All_Addresses: check representation_clauses (at, 'address); All_Input: check representation_clauses ('input, 'class'input); Sized_Objects: check representation_clauses (object 'size); count representation_clauses ('SIZE); -- check layout clauses for derived types: check representation_clauses (new layout); -- check layout clauses for root tagged types and type extensions: check representation_clauses (tagged extension layout); 5.47.3 Limitation ----------------- For the "fractional_size" and "non_contiguous_layout" subrules, there are some rare cases where AdaControl cannot evaluate the given size or elements of the record representation clause, and thus not detect the corresponding situation. Such cases are detected by the rule "uncheckable". *Note Uncheckable::. 5.47.4 Tips ----------- The specifiable attributes (the ones that can be given as parameters to this rule) are ''Address', ''Size', ''Component_Size', ''Alignment', ''External_Tag', ''Small', ''Bit_Order', ''Storage_Pool', ''Storage_Size', ''Write', ''Output', ''Read', ''Input', and ''Machine_Radix'. See Ada Reference Manual 13.3(77). Ada allows partial record representation clauses, i.e. it does not require all fields to be specified. This means that if you add a field to a record and forget to update the associated representation clause, there will be no compilation error. The "incomplete_record" subrule is handy for making sure that this does not happen. Derived types with a representation clause may suffer an efficiency penalty, since calling an inherited subrograms requires a change of representation. Representation clauses for tagged types are dubious, since these types have hidden fields added by the compiler.  File: adacontrol_ug.info, Node: Return_Type, Next: Side_Effect_Parameters, Prev: Representation_Clauses, Up: Rules reference 5.48 Return_Type ================ This rule controls that certain form of types are not used for function results. 5.48.1 Syntax ------------- return_type [( {, })]; ::= class_wide | limited_class_wide | constrained_array | protected | task | unconstrained_array | unconstrained_discriminated | anonymous_access 5.48.2 Action ------------- This rule controls functions whose return type belongs to one of the indicated type kinds: * 'class_wide' controls all class-wide types, while 'limited_class_wide' controls only limited class-wide types. * 'constrained_array' controls constrained array types * 'unconstrained_discriminated' controls types with discriminants (but not constrained subtypes of such types) * 'unconstrained_array' controls unconstrained array types * 'task' controls task types, or composite types that include tasks as subcomponents. * 'protected' controls protected types, or composite types that include protected objects as subcomponents. * 'anonymous_access' controls anonymous access types. If no subrule is specified, all type kinds are controlled. Note that more than one kind may apply to a type: for example, a function can return a class-wide type with discriminants that includes tasks and protected objects as subcomponents. In this case, several messages are issued for the same type. Ex: check return_type (unconstrained_discriminated, unconstrained_array);  File: adacontrol_ug.info, Node: Side_Effect_Parameters, Next: Silent_Exceptions, Prev: Return_Type, Up: Rules reference 5.49 Side_Effect_Parameters =========================== This rule controls calls that may depend on the order of evaluation of parameters. 5.49.1 Syntax ------------- side_effect_parameters ( {, }); 5.49.2 Action ------------- This rule controls subprogram calls or generic instantiations where different actual parameters call functions known to have side effects. This is dangerous practice, since correct behaviour may depend on a certain evaluation order of parameters, which is not specified by the language. All are functions that are assumed to interfere, i.e. the rule will signal if any of these functions is called more than once in the parameters of a call. As usual, the whole syntax for entities is allowed for . *Note Specifying an Ada entity name::. It is allowed to give the name of a generic function, or of a function declared in a generic package; in this case, all functions resulting from instantiations of these generics will be considered. In the case of renamings, you must give the name of the original function; the rule will work correctly if the call is made through a renaming of this function. Ex: check side_effect_parameters (F1); check side_effect_parameters (G1, G2); Here, F1 has a side effect, and the rule will signal if it is called more than once. G1 and G2 are assumed to interfere, and therefore the rule will signal if either is called more than once, or if both are called. However, having a call that mentions F1 and G2 is OK. 5.49.3 Limitation ----------------- Due to the size of internal structures, this rule may not be given more than 100 times. Due to an unimplemented feature of ASIS-for-Gnat, this rule will not process defaulted parameters, and hence not detect interferences due to calling a side-effect function through the default value.  File: adacontrol_ug.info, Node: Silent_Exceptions, Next: Simplifiable_Expressions, Prev: Side_Effect_Parameters, Up: Rules reference 5.50 Silent_Exceptions ====================== This rule controls exception handlers that can cause exceptions to silently disappear. 5.50.1 Syntax ------------- silent_exceptions ( {, }); element ::= | control-item ::= not | with | others report-item ::= raise | explicit_raise | reraise | return | requeue | 5.50.2 Action ------------- The rule controls handlers that do not call one of the given subprograms (for example a reporting procedure) nor perform other required operations, like returning, requeuing, or re-raising an exception. A parameter that starts with "not" or "with" is a and defines wich exceptions are controlled; the should be either an exception, or the name of a library unit (in which case, it applies to all exceptions declared in the library unit). As usual, the whole syntax for entities is allowed here. *Note Specifying an Ada entity name::. If the is (part of) a generic, then it applies to all exceptions from all corresponding instantiations. If there is no , then all exceptions are controlled. If several are given, the ones with "with" add exceptions to the set of controlled exceptions, and the ones with "not" remove exceptions, in order, starting from the empty set if the first is a "with", or starting from the set of all exceptions if the first is a "not". See examples below. "'when others'" handlers are always controlled, unless there is an explicit "not others" . A "with others" can be specified to check _only_ "'when others'" handlers. The other parameters are and define the constructs considered "reporting". should correspond to an Ada callable entity or generic package; as usual, the whole syntax for entities is allowed here. *Note Specifying an Ada entity name::. If a generic procedure or function is given, then all corresponding instances are considered reporting subprograms. If a generic package is given, any instantiation (in an inner block of the handler) is considered reporting. In addition, the special names "explicit_raise", "reraise", "return" and "requeue" mark raise statements with an explicit exception name, raise statements without an exception name, return statements (including extended return statements), and requeue statements (respectively) as reporting. "raise" is a shorthand for both "explicit_raise" and "reraise". If "explicit_raise" is given as a parameter, the procedure 'Ada.Exceptions.Raise_Exception' is automatically added to the list of procedures for both Check and Search, unless it is explicitely specified as a parameter in a rule; and similarly 'Ada.Exceptions.Reraise_Occurrence' is added for "reraise". This way, it is possible to consider them as reporting procedures for Check (for example) and not for Search. A handler where _all_ exceptions are uncontrolled is not controlled at all (i.e. it is allowed to be non reporting). Otherwise, the rule reports if the handler does not contain at least one of the in each possible path of the handler. If the appear only in 'if' or 'case' statements, but not in all possible paths, or if they appear only in the body of 'loop' statements, the rule will issue a message asking for a manual verification, since it cannot be statically determined whether the proper treatment happens in every case. Note that the purpose of this rule is to require the reporting calls to be "eye-visible", i.e. textually written in the exception handler. For example, the rule will accept a call to a procedure inside the sequence of statements of a package body declared in some inner block; however, it will not accept the same call if it is in the sequence of statements of a package instantiation (unless the generic package is itself mentionned as reporting), because the call is not "eye-visible". For the same reason, a call to a reporting function which happens as the default value of an omitted parameter in some other call will not be accepted. This rule can be given once for each of check, search and count. This way, it is possible to have a level considered a warning (search), and one considered an error (check). Ex: -- Make an error if exception is not reraised and does not call -- Reports.Trace, but make it only a warning if the exception is an -- IO exception or Constraint_Error: check silent_exceptions (not ada.io_exceptions, not standard.constraint_error, raise, reports.trace); search silent_exceptions (raise, reports.trace); -- check handlers that do not reraise the exception, except for -- IO exceptions: check silent_exceptions (not Ada.IO_Exceptions, reraise); -- Same for predefined exceptions, except Constraint_Error: check silent_exceptions (not Standard, with Standard.Constraint_Error, reraise); -- Same for all exceptions named User_Error, wherever they are declared, -- and no others check silent_exceptions (with all User_Error, reraise); -- Same for "when others" handlers check silent_exceptions (with others, reraise); 5.50.3 Limitations ------------------ Currently, "return" includes all return statements. It would be nice to separate function returns from procedure or accept returns. This is expected to be done in some future version of AdaControl. There are two cases that are not statically checkable, and thus may not be identified by this rule: if an exception is raised in an inner block statement and handled locally, and if the exception handler aborts the current task. If a reporting function is given, there are a few cases where the calls will not be recognized: * inside a pragma * in a representation clause * in a code statement (i.e. as a field of a machine code instruction) This limitation is intentional: these are such weird places to call a reporting function that it seems better to draw attention to it...  File: adacontrol_ug.info, Node: Simplifiable_Expressions, Next: Simplifiable_Statements, Prev: Silent_Exceptions, Up: Rules reference 5.51 Simplifiable_Expressions ============================= This rule controls expressions that can be simplified in various ways. 5.51.1 Syntax ------------- simplifiable_expressions [( {, })]; ::= conversion | logical | logical_false | logical_not | logical_true | parentheses | range 5.51.2 Action ------------- Without parameters, all kinds of simplifiable expressions are controlled; otherwise, the controlled expressions depend on the subrule: * "conversion" controls type conversions where the expression is of a universal type (a litteral or named number), or where the target subtype is either the same as the expression's subtype, or the first named subtype of the expression. * "logical_true" controls redundant boolean expressions of the form ' = True' (or '/='), and "logical_false" does the same for comparisons with 'false'. * "logical_not" controls 'not' operators whose argument is a comparison (which could be inverted). * "logical" is the same as specifying "logical_true", "logical_false" and "logical_not". * "parentheses" controls unnecessary parentheses like those surrounding the expression of an assignment, an "if" or a "case" statement, or those that are not required by operators precedence rules. * "range" controls expressions of the form 'T'First .. T'Last' that should be 'T'range' (or even simply 'T'). This rule can be given at most once for each subrule. Ex: search simplifiable_expressions (parentheses); check simplifiable_expressions (range, logical); 5.51.3 Tips ----------- There are cases where parentheses may seem unnecessary, but are (purposedly) not reported by this rule. Consider for example: X := A + (B + C); Removing the parentheses would change the expression to mean: X := (A + B) + C; If the '"+"' operator has be redefined and is no more associative, this would actually change the meaning of the program. In a less contrieved example, note that: X mod (A*B) is not the same as: X mod A * B For these reasons, and to make the rule easier to understand for the user, the rule does not report unnecessary parentheses between operators of identical priority levels. Conversion of universal value is never necessary, however there are cases where overloading resolution may require the conversion to be replaced by a qualification, rather than being simply removed.  File: adacontrol_ug.info, Node: Simplifiable_Statements, Next: Statements, Prev: Simplifiable_Expressions, Up: Rules reference 5.52 Simplifiable_Statements ============================ This rule controls statements that can be removed or simplified in various ways without changing the meaning of the program. 5.52.1 Syntax ------------- simplifiable_statements [( {, })]; ::= block | dead | handler | if | if_for_case | if_not | loop | loop_for_while | nested_path | null 5.52.2 Action ------------- Without parameter, all kinds of simplifiable statements are controlled; otherwise, the controlled statements depend on the subrule: * 'block' controls block statements that have no labels, no declarations, and no exception handlers. * 'dead' controls dead code, i.e. statements that are statically known to be never executed. This includes statements that follow a 'return', 'requeue', or 'goto' statement, or an 'exit' statement that is either unconditional or whose condition is statically known to be true. It includes also 'while' statements and 'if' statements (including 'elsif' paths) whose condition is statically false, and 'for' loops whose range is statically empty. * 'handler' controls "trivial" exception handlers, i.e. handlers whose sequence of statements includes only a single 'raise' statement without an exception name. However, a handler is not reported if there is also a non trivial handler for 'others'. These examples show the situation: exception when Constraint_Error => -- Reported (no when others) raise; end; exception when Constraint_Error => -- Reported (trivial when others) raise; when others => -- Reported raise; end; exception when Constraint_Error => -- Not reported (non trivial when others) raise; when others => Put_Line ("Error"); end; * 'if' controls 'if' statements with an 'else' path that contains only 'null' statements (and can thus be removed). * 'if_for_case' controls usage of 'if' statements that could be replaced by 'case' statements. An 'if' statement is assumed to be replaceable if it has at least one 'elsif' and all conditions are comparisons (or membership tests, possibly connected by logical operators) of the same discrete variable with static values. Typically, this subrule will spot constructs like: if X = 1 then ... elsif X = 2 or X = 3 or X = 4 then ... elsif X >= 5 and X <= 10 then ... elsif X in 11 .. 20 then ... else ... end if; * 'if_not' controls 'if' statements with an 'else' path and no 'elsif' path, and where the condition is given in negative form (i.e. it is a 'not', or a '"/="' comparison). Such statements could be made positive (and thus less error-prone) by interverting the 'if' and 'else' paths. * 'nested_path' controls paths from 'if' statements that can be moved outside. This happens if the 'if' has only 'then' and 'else' paths, and either of them ends with a "breaking" statement ('raise', 'return', 'exit' or 'goto'); in this case, the other path needs not be nested inside the 'if' statement. However, if both paths end with the same "breaking" statement, no error is reported. In short, the rule signals the following examples: if Cond then return; else I := 1; end if; if Cond then I := 1; else return; end if; because they can be changed to: if Cond then return; end if; I := 1; if not Cond then return; end if; I := 1; The rule will not signal the following example, where both paths end with the same "breaking" statement ('return'), because it would break the symetry of the statement: if Cond then return 1; else return 2; end if; * 'null' controls 'null' statements that serve no purpose and can be removed. Note that if a 'null' statement carries a label, it is not considered simplifiable. * 'loop' controls 'while' loop statements where the condition is a plain 'True', and can thus be changed to simple loops. * 'loop_for_while' controls simple loop statements whose first statement is an 'exit' (for the same loop), and which can therefore be turned into a 'while' loop. This rule can be given at most once for each subrule. Ex: check simplifiable_statements (block, null); search simplifiable_statements (if); 5.52.3 Tips ----------- 'loop' may seem a strange thing to check, since no Ada programmer is supposed to write this. However, experience shows that it is a good indicator of code written by people who did not get proper Ada training. Such code is certainly worth a peer review...  File: adacontrol_ug.info, Node: Statements, Next: Style, Prev: Simplifiable_Statements, Up: Rules reference 5.53 Statements =============== This rule controls usage of certain Ada statements. 5.53.1 Syntax ------------- statements ( {, }; ::= any_statement | abort | accept | accept_return | assignment | asynchronous_select | block | case | case_others | case_others_null | code | conditional_entry_call | declare_block | delay | delay_until | dispatching_call | effective_declare_block | entry_call | entry_return | exception_others | exception_others_null | exit | exit_expanded_name | exit_for_loop | exit_outer_loop | exit_plain_loop | exit_while_loop | exited_extended_return | extended_return | for_in_loop | for_iterator_loop | for_of_loop | function_return | goto | if | if_elsif | inherited_procedure_call | labelled | loop_return | multiple_exits | named_exit | no_else | null | procedure_return | raise | raise_locally_handled | raise_nonpublic | raise_standard | redispatching_call | reraise | requeue | selective_accept | simple_block | simple_loop | terminate | timed_entry_call | unconditional_exit | unnamed_block | unnamed_exit | unnamed_loop_exited | unnamed_for_loop | unnamed_multiple_loop | unnamed_simple_block | unnamed_simple_loop | unnamed_while_loop | untyped_for | while_loop 5.53.2 Action ------------- Subrules that are Ada keywords control the corresponding Ada statements. The meaning of other subrules is as follows: * 'any_statement' controls all statements. This is of course not intended to forbid all statements in a program (!), but _counting_ all statements can be quite useful. * 'accept_return' controls return statements that return from an 'accept' statement, 'entry_return' controls return statements that return from a (protected) entry body, and 'procedure_return' controls return statements that return from a procedure. 'loop_return' controls return statements (including extended return statements) that appear inside a 'loop' statement. * 'assignment' controls all assignment statements. * 'asynchronous_select' controls the 'select' ... 'then abort' statement. 'conditional_entry_call' controls the 'select' ... 'else' statement. 'timed_entry_call' controls the 'select' ... 'or delay' statement. 'selective_accept' controls the regular 'select' statement. * 'block' controls all block statements, while 'unnamed_block' controls blocks without a name, 'declare_block' controls blocks with an explicit 'declare' (even if the declarative part is empty), and 'effective_declare_block' controls blocks with a declarative part that includes anything else than 'use' clauses and pragmas. 'simple_block' controls block statements that have no declarative part (or an empty declarative part) and no exception handlers, and 'unnamed_simple_block' does the same, but only for blocks without a name. * 'case' controls all 'case' statements. * 'case_others' controls any 'when others' path in a 'case' statement, while 'case_others_null' controls only 'when others' paths in a 'case' statement that contain only 'null' statements. * 'code' controls code statements. * 'delay' controls only relative 'delay' statements, while 'delay_until' controls absolute 'delay until' statements. * 'dispatching_call' controls all dispatching calls. Note that this subrule controls dispatching procedure calls as well as dispatching function calls, although the latter is technically an expression and not a statement. 'redispatching_call' does the same, but only for dispatching calls that are (directly or indirectly) inside a primitive operation of a tagged type. * 'entry_call' controls all entry call statements, including those that are part of a conditional or timed entry call statement. * 'exit' controls all exit statements, while 'exit_for_loop', 'exit_while_loop', and 'exit_plain_loop' control 'exit' statements that terminate 'for' loops, 'while' loops, and plain (neither 'for' nor 'while') loops, respectively. 'unconditional_exit' controls 'exit' statements without a 'when' condition. 'multiple_exits' controls loop that have more than one 'exit' statement. 'unnamed_loop_exited' controls exit statements that terminate an unnamed loop. 'exit_outer_loop' controls 'exit' statements that exit from an outer loop (i.e. not the innermost one). 'exit_expanded_name' controls named 'exit' statements where the name is given as an expanded name. * 'exception_others' controls any 'when others' exception handler, while 'exception_others_null' controls only 'when others' exception handlers that contain only 'null' statements. * 'extended_return' controls extended return statements (i.e. the Ada 2005 construct "'return V : T do ... end return'"). 'exited_extended_return' controls extended return statements that can be left without actually returning due to an exit or goto statement within their sequence of statements. * 'for_loop' controls all 'for' loops, while 'for_in_loop' controls only the traditional form of 'for' loop ('for I in range loop'), 'for_iterator_loop' controls the iterator form ('for I in Iterator loop'), and 'for_of_loop' controls the components form ('for V of ... loop') (the three latter forms are not available with the old gnat version of AdaControl). * 'function_return' controls return statements (including extended return statements) from functions. Obviously, return statements cannot be forbidden in functions; this keyword controls that there is only one return statement in the body of functions, and at most one return statement in each exception handler of the exception part of functions. * 'if' controls all 'if' statements. * 'if_elsif' controls 'if' statements that have at least one 'elsif'. * 'inherited_procedure_call' controls calls to procedures that have been inherited by a derived type and not redefined. * 'labelled' controls statements with a label (true statement labels, not block and loop names). * 'named_exit' controls 'exit' statements with a loop name. * 'no_else' controls 'if' statements that have no 'else' path. * 'null' controls all 'null' statements. * 'raise' controls all 'raise' statements. * 'reraise' controls 'raise' statements in exception handlers that reraise the same exception, and calls to the 'Ada.Exceptions.Reraise_Occurrence' procedure. * 'raise_standard' controls 'raise' statements that raise one of the predefined exceptions (those declared in package 'Standard'). 'raise_nonpublic' controls statements that raise exceptions that are neither predefined nor defined in the visible part of a package which is the enclosing library unit of the statement. 'raise_locally_handled' controls statements that raise an exception which is handled by a handler in the same subprogram body as the statement. Note that for these subrules, the exception can be raised either by a 'raise' statement, or by a call to 'Ada.Exceptions.Raise_Exception' where the raised exception is statically determinable. * 'simple_loop' controls simple loops, i.e. those that are neither 'while' nor 'for' loops. * 'unnamed_exit' controls 'exit' statements without a loop name that exits from a named loop. * 'unnamed_for_loop', 'unnamed_simple_loop', and 'unnamed_while_loop' control loops of the given kind that are not named. * 'unnamed_multiple_loop' controls nested loops that are not named (i.e. under this rule, only loops that contain no inner loop, and are not nested in another loop, are allowed not to be named). The kind of loop (plain, 'for', 'while') is not considered. * 'untyped_for' controls 'for' loops that use a range without an explicitely named type (i.e. 'for I in 1..10 loop'). Using a ''Range' attribute is OK. * 'while_loop' controls all 'while' loops. Ex: search statements (delay); check statements (goto, abort); check statements (case_others_null, exception_others_null); 5.53.3 Tips ----------- It may seem strange to control things like 'if' or 'case' statements, since no coding standard would prohibit their use. However, this may be useful, especially with "count", for statistical purposes, like measuring the ratio of 'if' to 'case' statements. The plain "raise" subrule controls the 'raise' statement, and only this one. If you want to check all places where exceptions can be raised, use also the "entities" rule like this: "all raise": check statements (raise), check entities (Ada.Exceptions.Raise_Exception, Ada.Exceptions.Reraise_Occurrence); Other subrules of the "raise" family are more about which kind of exception is being raised, and therefore control also exceptions raised by calling the procedures from 'Ada.Exceptions'. "inherited_procedure_call" controls only procedure calls. For function calls, see rule *note Expressions::.  File: adacontrol_ug.info, Node: Style, Next: Terminating_Tasks, Prev: Statements, Up: Rules reference 5.54 Style ========== This rules controls usage of various "general" Ada coding style. 5.54.1 Syntax ------------- style; style (casing_attribute, {,}); style (casing_identifier, {,}); style (casing_keyword, {,}); style (casing_pragma, {,}); style (compound_statement); style (default_in); style (exposed_literal, , {, }); style (formal_parameter_order {, }); style (multiple_elements {,}); style (negative_condition); style (no_closing_name [, ]); style (numeric_literal, [not] [, ]); style (parameter_order {, }); style (renamed_entity); ::= uppercase | lowercase | titlecase | original ::= [flexible] clause | declaration | statement | handler | begin | end | then | when | else | is | loop | do | keywords ::= {| } ::= in | defaulted_in | access | in_out | out | type | procedure | function | package ::= integer | real | character | string ::= | ::= [max] | | "" ::= constant | exponent | index | number | pragma | repr_clause | var_init | type 5.54.2 Action ------------- The first parameter specifies which style aspect is to be checked: * "casing_attribute", "casing_keyword", "casing_identifier", and "casing_pragma" control that attributes (respectively keywords, identifiers, or pragmas) use the appropriate casing. "original" (which is allowed only for identifiers) means that identifiers must use the same casing as in their declaration. If more than one is given, it means that any of them is allowed. * "compound_statement" controls that compound statements span at least a minimum number of lines: 3 for 'if' statements, 'loop' statements, block statements, and 'accept' statements with a body; 4 for 'case' statements, selective 'accept' statements, and timed entry call statements; and 5 for conditional entry call statements and asynchronous select statements. * "default_in" controls subprograms, entries and generics declarations that omit an explicit 'in' mode for a parameter. Access parameters are not reported, since an an explicit 'in' is not allowed in that case. * "exposed_literal" controls the usage of literals (aka "magic values"), that appear outside of allowed places. The second parameter tells to which kind of literals the rule applies. The (optional) indicated values that follow are allowed at any place; for integers, a single value can be preceded by "max", to indicate that all literals whose (absolute) value is less or equal are allowed; for strings, the values are regular expressions. *Note Syntax of regular expressions::. Commonly allowed values are 0 and 1 for integer literals, 1.0 and 0.0 for real literals and "^$" (the empty string) for string literals. At most 20 values of each kind may be specified. In addition, one or several keyword can be used to specify constructs where any literal is allowed: "declaration" stands for any declaration, "constant" for constant declarations, "exponent" for the right parameter of an exponentiation (i.e. '"**"') function call, "index" for array indexing, "number" for named number declarations, "pragma" for pragma arguments, "repr_clause" for representation clauses, "type" for type (and subtype) declarations, and "var_init" for the initialization expression of variable declarations. If no is given, it is taken as 'number, constant', i.e. any literal is allowed in named numbers and constant declarations. * "multiple_elements" controls clauses, declarations, statements, and handlers that do not start on a line of their own (i.e. when there are more than one of these on the same line). Similarly, 'begin', 'end', 'then' and 'when' are required to be on a line of their own, together with the possible keyword or identifier attached to them and the semi-colon. In addition, the 'is', 'loop' or 'do' that terminates the first part of some declarations or statements is required to be on the same line as the begining of the element, or on a line of its own. Extra parameters specify which kind of element to check; if not specified, all kind of elements are controlled. "keywords" is a shorthand for specifying all keywords. If "flexible" is specified in front of "clause" (not allowed otherwise), it allows a 'use' clause to be on the same line as a 'with' clause, provided all packages named in the 'use' clause are also named in the preceding 'with' clause. * "negative_condition" controls "if" statements with an "else" part and no "elsif", where the condition starts with a 'not', and should therefore preferably be expressed positively. * "no_closing_name" controls declarations, like package or subprograms, that allow (but do not require) repeating the name at the end of the declaration, and where the closing name is omitted (which is considered bad style in general). However, it can be acceptable to allow the omission of closing names for very short constructs; therefore this rule has an optional parameter specifying the maximum number of lines of a construct for which omitting the closing name is allowed. This rule can be given only once for each of check, search and count. This way, it is possible to have a length considered a warning (search), and one considered an error (check). Of course, this makes sense only if the length for search is less than the one for check. If no length is specified, all occurrences of missing closing names are signaled. * "numeric_literal" controls the presentation of numeric literals, depending on the base (wich, as required by Ada rules, must be in the range 2..16). If "not " is specified as the second parameter, the given base may not be used for based literals. Otherwise, there must be a third (integer) parameter to specify the size of blocks of digits for that base, i.e. there must be an underscore character to separate digits every position. Typically, is 3 for base 10, 4 for base 2, etc. * "parameter_order" and "formal_parameter_order" control the order of the declarations of parameters or generic formal parameters, respectively. Each parameter of the rule consists in one or several of the "mode" keywords, and describes, in order, which kind of parameter is allowed. All modes not specified explicitely are allowed after the ones that are specified. See examples below. If no parameter is given, the order for regular parameters is "in" or "access" first, then "in_out", then "out", then "defaulted_in". The order for formal_parameters is "type" first, then "in" "defaulted_in" and "access", then "in_out", then "procedure" and "function", then "package". * "renamed_entity" controls occurrences of identifiers within the scope of a renaming declaration for them; i.e. it enforces that when an entity has been renamed, the original name should not be used anymore. Ex: search style (no_closing_name); search style (no_closing_name, 5); check style (casing_identifier, original); check style (default_in); check style (numeric_literal, 10, 3); check style (exposed_literal, integer, 0, 1); check style (exposed_literal, real, 0.0, 1.0); -- in parameters (with or without default) and access -- parameters must be first, then in out parameters, then -- out parameters. In parameters are allowed last if they -- have defaults. check style (parameter_order, in | defaulted_in | access, in_out, out defaulted_in); -- For generics, formal objects must come first, then formal -- types, then formal subprograms, then formal package: check style (formal_parameter_order, in | in_out, type, procedure | function, package); Without parameter, the rule will control all style aspects with parameter values that correspond to the most commonly used cases, i.e. it is equivalent to the following: style (no_closing_name); style (casing_attribute, titlecase); style (casing_keyword, lowercase); style (casing_identifier, original); style (casing_pragma, titlecase); style (default_in); style (negative_condition) style (multiple_elements) style (literal, 10, 3); style (exposed_literal, integer, 0, 1) style (exposed_literal, real, 0.0, 1.0); 5.54.3 Tips ----------- For the "Casing_Identifier" subrule, if the value is "original", subprogram and parameter names from the body are checked against those from the specification (if any). This is what the user would expect, although strictly speaking it is not a usage of the name. Note that operators always follow the casing rule for keywords, even for calls that use the infix notation (i.e. in '"and"(A, B)'). Having more than one allowed casing is useful if for example you want to require Titlecase, but accept that the original casing be used (maybe because your editor or pretty-printer forces it). For the "Exposed_Literal" subrule, negative values can be specified as being allowed; negative numbers are handled as if they were literals. This is what the casual user would expect, but to the language lawyer, "-1" is not a negative literal, it is a unary minus operator applied to the positive value "1". "compound_statement" was a simplistic way of finding badly laid-out statements, at a time when "multiple_elements" did not control the end or intermediate parts of declarations and statements. It is of little use now that "multiple_elements" has been enhanced. 5.54.4 Limitations ------------------ If a predefined operator or an attribute is renamed, the "renamed_entity" subrule cannot check that the original entity is not used in the scope of the renaming. Such cases are detected by the rule "uncheckable". *Note Uncheckable::.  File: adacontrol_ug.info, Node: Terminating_Tasks, Next: Type_Initial_Values, Prev: Style, Up: Rules reference 5.55 Terminating_Tasks ====================== This rule controls tasks that can terminate. 5.55.1 Syntax ------------- terminating_tasks 5.55.2 Action ------------- A task is considered a terminating task if its last statement is not an unconditional loop, or this if this loop is exited. It is also considered terminating if it contains a selective accept with a 'terminate' alternative. Since this rule has no parameters, it can be given only once. Ex: check terminating_tasks; 5.55.3 Tips ----------- There is still one case where a task terminates, which is not reported by this rule: when a task is aborted. This is intended, since there are cases (like mode changes) where a logically non-terminating task is aborted. If aborts are also to be reported, use the rule "statements (abort)". *Note Statements::.  File: adacontrol_ug.info, Node: Type_Initial_Values, Next: Type_Usage, Prev: Terminating_Tasks, Up: Rules reference 5.56 Type_Initial_Values ======================== This rule controls that a special constant is declared together with each type, for example to serve as a default initial value. 5.56.1 Syntax ------------- type_initial_values [("")]; 5.56.2 Action ------------- This rule controls types that do not feature an initialization constant declared in the same declarative part as the type. If no is given, any constant is considered an initialization constant for its type; otherwise, only constants whose name matches the given pattern are considered initialization constants. Ex: check type_initial_values ("^C_Init_"); The above example will ensure that every declared type features a constant of the type whose name starts with "C_Init_".  File: adacontrol_ug.info, Node: Type_Usage, Next: Uncheckable, Prev: Type_Initial_Values, Up: Rules reference 5.57 Type_Usage =============== This rule controls usage of indicated types, either individually or by category. 5.57.1 Syntax ------------- type_usage (, {, }]); type_usage (index, | {, }]); ::= () | access | array | delta | digits | mod | protected | range | record | tagged | task ::= [not] representation | pack | size | component_size 5.57.2 Action ------------- If the first parameter is an attribute (a name starting with a simple quote), the rule controls all occurrences of the attribute where the prefix designates a type belonging to the given as second parameter. If the first parameter is "index", the rule controls all array types that have an index of the type given by , or belonging to the given as second parameter. As usual, the whole syntax for entities is allowed for . *Note Specifying an Ada entity name::. For both subrules, if one or several are given, only types featuring (or not featuring if "not" is given) the provided aspects are controlled. The meaning of is: * "()": The type is an enumerated type. * "access": The type is an access type. * "array": The type is an array type. * "delta": The type is a fixed point type (it is not currently possible to distinguish ordinary fixed point types from decimal fixed point types). * "digits": The type is a floating point type. * "mod": The type is a modular type. * "protected": The type is a protected type. * "range": The type is a signed integer type. * "record": The type is an (untagged) record type. * "tagged": The type is a tagged type (including type extensions). * "task": The type is a task type. The meaning of is: * "representation": the type has an enumeration representation clause or a record representation clause. * "pack": the type is the target of a pack 'pragma'. * "size" and "component_size": the type has the corresponding attribute specified. Ex: -- Don't use the 'Pos attribute for enumerated types with a representation check type_usage ('Pos, (), representation); -- Don't use modular type for array indexes check type_usage (index, mod); 5.57.3 Tips ----------- The subrule "index" controls the use of a type as an index at any position and irrespectively of the number of indices of the array. To control a precise pattern of types used as indices, use the rule "array_declarations". *Note Array_Declarations::. The subrule that uses attribute names does not allow an . To control occurrences of an attribute on a precise type, use the rule "entities". *Note Entities::.  File: adacontrol_ug.info, Node: Uncheckable, Next: Unit_Pattern, Prev: Type_Usage, Up: Rules reference 5.58 Uncheckable ================ This rules controls cases where it is not possible to guarantee the accuracy of checks performed by AdaControl, and where manual inspection may be required. 5.58.1 Syntax ------------- uncheckable [( [,])]; ::= false_positive | false_negative | missing_unit 5.58.2 Action ------------- If the keyword "missing_unit" is given, this rule controls missing units, i.e. units given on the command line that are not found (and therefore not controlled) will result in an usual error message. Otherwise, this rule controls constructs that are not static and prevent other rules from being fully reliable. This rule is special, since it really affects the way other rules behave when they encounter a statically uncheckable construct. Therefore, if a label is given, the message will include the label as usual, with an indication of the rule that triggered the message; if no label is given, the message will include the name of the rule that detected the uncheckable construct, not "uncheckable" itself. If the keyword "false_negative" is given, the rule will control constructs that could result in false negatives, i.e. possible violations that would go undected, while if the keyword "false_positive" is given, it will control constructs that could result in false positives, i.e. error messages when the rule is not really violated. If no keyword is given, both occurrences are controlled. As far as statistics are concerned (see *note Control kinds and report messages::), "uncheckable" messages from rules are counted under the corresponding rule's statistics (like other messages), but there will be also a count of all "uncheckable" messages under the rule "UNCHECKABLE", and also subtotals corresponding to the number of "uncheckables" for each rule. This rule can be given only once for each of value of the parameters. Ex: check uncheckable (false_negative); search uncheckable (false_positive); check uncheckable (missing_unit); 5.58.3 Tips ----------- This rule is especially important when AdaControl is used in safety critical software, since it will detect constructs that could escape verification. Such constructs should be either disallowed, or require manual inspection. On the other hand, in casual software, it may lead to many messages, since for example dispatching calls are uncheckable with many rules. 5.58.4 Limitation ----------------- With "missing_unit", the message does not include a reference to a source location, since there is no place in the source which can be considered as the origin of the error. If you run AdaControl from GPS, there will always be a separate category ("Uncheckable") in the locations window, under which the message will appear, with a file name of "none". Don't try to click on the error message, since GPS will find no file named "none"!  File: adacontrol_ug.info, Node: Unit_Pattern, Next: Units, Prev: Uncheckable, Up: Rules reference 5.59 Unit_Pattern ================= This rule controls various usage patterns of program units and elements declared in them. 5.59.1 Syntax ------------- unit_pattern (Single_Tagged_Type); unit_pattern (Tagged_Type_Hierarchy); unit_pattern (Context_Clauses_Order {, }); unit_pattern (Declarations_Order, , {, }); ::= {| } ::= with | use | use_type | pragma ::= package_public | package_private | package_body | subprogram ::= {| } ::= use | use_type | use_all_type | number | constant | variable | private_type | full_type | subtype | subprogram_spec | package_spec | generic_subprogram_spec | generic_package_spec | task_spec | protected_spec | subprogram_body | package_body | generic_subprogram_body | generic_package_body | task_body | protected_body | object_renaming | subprogram_renaming | package_renaming | exception_renaming | subprogram_instantiation | package_instantiation | exception | others 5.59.2 Action ------------- The checked pattern depends on the given subrule: * "single_tagged_type" controls that at most one tagged type is declared in any package. * "tagged_type_hierarchy" controls that tagged types follow packages hierarchy, i.e. that the parent of a type extension (derivation of a tagged type) is declared in the parent unit of the one that declared the derivation. * "context_clauses_order" controls the order of context clauses (and pragmas) given on top of the unit. Each parameter of the rule consists in one or several of the keywords, and describes, in order, which kind of clause is allowed. Note that "use_type" covers only the regular 'use type' clause, specify also "use_all_type" to include the Ada 2012 'use all type' clause as well. Note that all s not specified explicitely have no place, and thus are not allowed at all. * "declarations_order" controls the order of declarations (and use clauses) given in various parts, depending on the second parameter: * "package_public" controls elements in the visible part of a package specification; * "package_private" controls elements in the private part of a package specification; * "package_body" controls elements in the body of a package; * "subprogram" controls elements in the body of subprograms (procedures and functions) and entries. Each parameter of the rule consists in one or several of the keywords, and describes, in order, which kind of declaration is allowed. Note that all s not specified explicitely have no place, and thus are not allowed at all, unless "others" is given as the last parameter, in which case it covers all elements not part of any of the preceding parameters. See example below. Ex: check unit_pattern (single_tagged_type); check unit_pattern (tagged_type_hierarchy); -- All with clauses must come first, then use and use type clauses -- (freely mixed), then pragmas check unit_pattern (context_clauses_order, with, use | use_type | use_all_type, pragma); -- In the public part of a package, declare constants and named numbers -- first,then private types, then any of regular types, constants, and -- variables, then subprograms specifications (including generics and -- instantiations), then anything else: check unit_pattern (declarations_order, package_public, number | constant, private_type, full_type | constant | variable, subprogram_spec | generic_subprogram_spec | subprogram_instantiation, others); 5.59.3 Tips ----------- For "context_clauses_order" and "declarations_order", elements given as part of the same parameter (i.e. with a vertical bar between them) can be freely mixed, then followed by any of the elements of the next parameter, etc. An element may appear several times in different parameters. If the last parameter is "others", any element not mentionned at all is allowed after the ones for which you specify an order; this way, it is possible to specify an order for just some elements, and then don't care for the rest. Expression functions and null procedures are classified as "subprogram_spec" unless they are the completion of an explicit specification, in which case they are classified as "subprogram_body". If you don't want a declaration to appear at all, you can also use the rule "declarations". *Note Declarations::.  File: adacontrol_ug.info, Node: Units, Next: Unnecessary_Use_Clause, Prev: Unit_Pattern, Up: Rules reference 5.60 Units ========== This rule controls that all necessary units, and only those, are processed by AdaControl. 5.60.1 Syntax ------------- units [( [,])]; ::= unreferenced | unchecked 5.60.2 Action ------------- If the keyword 'unreferenced' is given, the rule controls compilation units that are part of the set of analyzed units, but withed by no other unit. If the keyword 'unchecked' is given, the rule controls compilation units that are withed by other unit(s), but not part of the set of controlled units (except standard units). This rule can only be given once for each of the subrules. Ex: check units (unchecked); search units (unreferenced); 5.60.3 Tip ---------- The main program will appear as unreferenced, since it is normally part of the controlled units, and not withed by any other unit. As usual, the corresponding message can be disabled by putting the comment: --## rule line off units on the main program.  File: adacontrol_ug.info, Node: Unnecessary_Use_Clause, Next: Unsafe_Elaboration, Prev: Units, Up: Rules reference 5.61 Unnecessary_Use_Clause =========================== This rule controls 'use' clauses that do not serve any purpose. 5.61.1 Syntax ------------- unnecessary_use_clause [( {,})]; ::= unused | qualified | operator | nested | movable 5.61.2 Action ------------- The rule controls 'use' clauses that can safely be removed, moved, or changed to a 'use type' clause. This happens in the following cases: * "unused": a 'use' clause is given, but no element from the corresponding package is mentionned in its scope. The message starts with "unused:". In this case, the 'use' clause can safely be removed. * "qualified": a 'use' clause is given, but all elements from the corresponding package are refered to using a qualified name (i.e. prefixed by the name of the package). The message starts with "all uses qualified:". In this case, the 'use' clause can safely be removed, but you may want to keep it for documentation purposes, since the package is actually used within this scope. * "operator": a 'use' clause is given, but the only elements that do not use a qualified name are operators. The message starts with "only used for operators:". In this case, and except for some pathological cases (definition of operators that are not primitive operations of the corresponding type), the 'use' clause can be replaced by one or several 'use type' clause(s). * "nested": a 'use' clause is given within the scope of an enclosing 'use' clause for the same package. The message tells the location of the other 'use' clause. If you also have a message that the outer 'use' clause is unnecessary, this means that all references to the package appear inside the inner 'use' clauses, and that the outer one can be removed. If not, you can either remove the inner 'use' clauses, or remove the outer one and add more local 'use' clauses where necessary. * "movable": a 'use' clause is given in a package specification, but all uses are from the corresponding body. The message starts with "use clause can be moved to body:". In this case, the 'use' clause can safely be moved to the body, unless it appears in a library package, and there are unqualified references to its elements from child units. If no parameter is given, all cases are controlled, otherwise only cases corresponding to the specified keyword(s) are controlled. This rule can be given only once for each value of the parameters. Ex: remove: search unnecessary_use_clause (unused); use_type: check unnecessary_use_clause (operator); 5.61.3 Tip ---------- This rule checks only usage of 'use' clauses. The rule "reduceable_scope" can be used to check that 'use' clauses do not span unnecessarily to wide a scope. *Note Reduceable_Scope::. 5.61.4 Limitations ------------------ There are some rare cases where the rule may signal that a 'use' clause is not necessary, where it actually is. There is no risk associated to this since if you remove the 'use' clause, the program will not compile. The first one comes from a limitation of the ASIS standard: if the only use of the 'use' clause is for making the "root" definition of a dispatching call visible. The second one comes from a limitation in ASIS-for-Gnat. This happens when the only use of the 'use' clause is for making an implicitely declared operation (an operation which is declared by the compiler as part of a type derivation) visible, and when: * the operation is the target of a renaming declaration; * or the operation is passed as an actual to a generic instantiation; * or all operands of the operation are universal (i.e. untyped). Since these problems come from intrinsic limitations of ASIS, there is nothing we can do about it. When this happens, you can disable the unnecessary_use_clause rule using the line (or block) disabling feature. *Note Disabling controls::. Note that for the third alternative of the second case, you can also qualify one of the parameters, so it is not universal any more.  File: adacontrol_ug.info, Node: Unsafe_Elaboration, Next: Unsafe_Paired_Calls, Prev: Unnecessary_Use_Clause, Up: Rules reference 5.62 Unsafe_Elaboration ======================= This rule controls (generic) packages that may be subject to elaboration order dependencies. 5.62.1 Syntax ------------- unsafe_elaboration; 5.62.2 Action ------------- The rule controls library packages (or generic packages) whose elaboration calls or instantiates elements from other units (except language defined units) that are not subject to a 'pragma' 'Elaborate' or 'Elaborate_All'. The elaboration of such packages may depend on elaboration order. Since this rule has no parameters, it can be given only once. Ex: check unsafe_elaboration; 5.62.3 Tips ----------- If the package contains tasks, they are considered as being part of the elaboration code of the package, since tasks could be started by the elaboration of the package. This is somehow pessimistic in the unlikely case where a package would contain a local task type (whose specification is not part of the package specification) and no task object of that type is declared. Anyway, this could create only false positives, therefore there is no risk associated to it.  File: adacontrol_ug.info, Node: Unsafe_Paired_Calls, Next: Unsafe_Unchecked_Conversion, Prev: Unsafe_Elaboration, Up: Rules reference 5.63 Unsafe_Paired_Calls ======================== This rule controls usage of calls to operations that are normally paired (like P/V operations) and do not follow a "safe" coding pattern. 5.63.1 Syntax ------------- unsafe_paired_calls (, [, ]); ::= ::= ::= 5.63.2 Action ------------- The following explanations are given in terms of "locks" since this is the primary use of this rule, however the rule can be used for any calls that need to be properly paired. The rule can deal with three different kinds of locks: * abstract state machines: There is no "lock" object, locking is done directly inside the procedures. The parameter of the rule must not be provided in that case. * object abstract data types: The procedure operates on an object (generally of a private type) representing the "lock" object, passed as an "in out" parameter. The third parameter must be the corresponding type, and the rule will control that all matching pairs of calls refer statically to the same variable. * reference abstract data types: The procedure operates on a reference that designates the "lock" object, passed as an "in"parameter. The third parameter must be the corresponding type, which must be discrete or access, and the rule will control that all matching pairs of calls refer statically to the same value (for discrete types) or to the same constant (for access types). As usual, the whole syntax for entities is allowed for . *Note Specifying an Ada entity name::. The "safe" coding pattern is defined as follows: * A call to the first procedure is the first statement of a handled sequence of statements; * A call to the second procedure is the last statement of the same handled sequence of statements; * Corresponding calls of a pair use the appropriate value for the "lock" parameter (if any), as explained above. * There is no other call to either operation in the statements of the handled sequence of statements, except in nested blocks or accept statements; calls in such inner statements shall not reference the same values or variables as outer ones. * There is an exception handler for "others" in the handled sequence of statements. * Every exception handler of the handled sequence of statements includes a single call to the second operation, using the appropriate value or variable for the lock parameter. Typically, the "safe" pattern corresponds to the following structures: -- Abstract state machine begin P; -- Do something V; exception when others => V; -- handle exception end; -- Object abstract data type declare My_Lock : Lock_Type; begin P (My_Lock); -- Do something V (My_Lock); exception when others => V (My_Lock); -- handle exception end; -- Reference abstract data type declare Lock_Ptr : constant Lock_Access := Get_Lock; begin P (Lock_Ptr); -- Do something V (Lock_Ptr); exception when others => V (Lock_Ptr); -- handle exception end; Ex: check unsafe_paired_calls (Semaphore.P, Semaphore.V, Semaphore.Lock_Access); 5.63.3 Tips ----------- If the parameter is provided, both procedures must have a single parameter of the given type, it must not correspond to an "out" parameter, and if it corresponds to an "in" parameter, the type must be discrete or access. This rule can be specified several times, and it is possible to have the same procedure belonging to several rules. For example, if you have a 'Mask_Interrupt' procedure that should be matched by either 'Unmask_Interrupt' or 'General_Reset' (all declared in package 'IT_Driver'), you can specify: check unsafe_paired_calls (IT_Driver.Mask_Interrupt, IT_Driver.Unmask_Interrupt); check unsafe_paired_calls (IT_Driver.Mask_Interrupt, IT_Driver.General_Reset); Normally, the legality of a rule is checked when the rules file is parsed, and execution does not start if there is any error. However, the legality of the provided type can be checked only during the analysis. If the type is incorrect for some reason, a proper error message is issued and execution stops immediately. 5.63.4 Limitation ----------------- Due to a weakness of the ASIS standard, dispatching calls are not considered. Especially, this means that the cannot be class-wide. Such calls are detected by the rule "uncheckable". *Note Uncheckable::. Due to a size limitation of internal data structures, this rule can be specified at most 32 times.  File: adacontrol_ug.info, Node: Unsafe_Unchecked_Conversion, Next: Usage, Prev: Unsafe_Paired_Calls, Up: Rules reference 5.64 Unsafe_Unchecked_Conversion ================================ This rule controls unchecked conversions between types which are not statically known to have identical sizes. 5.64.1 Syntax ------------- unsafe_unchecked_conversion 5.64.2 Action ------------- This rule controls instances of 'Unchecked_Conversion' between types where the following conditions are not met: * A size clause has been specified for both types * Both sizes are equal Moreover, a special message is given if any of the types is a class-wide type (certainly a very questionable construct!). Ex: check unsafe_unchecked_conversion 5.64.3 Limitation ----------------- There are cases where a size clause is given for a type, but AdaControl is unable to evaluate it. This happens especially if the size clause refers to a size attribute of a predefined type, like: for T'Size use Integer'size; This can lead to false positives (i.e. detection of instantiations of 'Unchecked_Conversion' that are actually OK). Such cases are detected by the rule "uncheckable". *Note Uncheckable::.  File: adacontrol_ug.info, Node: Usage, Next: Use_Clauses, Prev: Unsafe_Unchecked_Conversion, Up: Rules reference 5.65 Usage ========== This rule controls how certain entitities (variables, constants, types, procedures, functions, exceptions, tasks, protected objects, and generics) are used. 5.65.1 Syntax ------------- usage (variable|object {,[not] | read | written | initialized}); usage (constant {,[not] | read}); usage (type {,[not] | used}); usage (procedure {,[not] | called | accessed}); usage (function {,[not] | called | accessed}); usage (exception {,[not] | raised | handled}); usage (task {,[not] | called | aborted}); usage (protected {,[not] | called}); usage (generic {,[not] | instantiated}); usage (all {,[not] }); ::= from_visible | from_private | from_spec 5.65.2 Action ------------- The first parameter defines the class of entities to be controlled. "object" stands for both "constant" and "variable", "type" stands for both types and subtypes, and "all" stands for all classes. If only one parameter is given, usage of all entities belonging to the indicated class are reported . Otherwise, other parameter(s) are keyword that restrict the kind of usage being controlled. "[not] from_visible", "[not] from_private", and "[not] from_spec" restrict entities being checked to those that appear (or not) in (generic) package specifications, in the visible part, in the private part, or in any part, respectively. "accessed" (available for subprograms only) restricts entities being checked to those that appear as the prefix of a ''Access' or ''Address' attribute. Other keywords carry their obvious meaning, and are allowed only where appropriate. The rule will output the information only for objects that match all the conditions given. A combination of parameters can be given only once for each of "check", "search", and "count". The report includes the kind of unit that declares the entity (normal unit, instantiation, or generic unit), the part where it is declared (visible or private) if it is declared in a (generic) package, and whether the entity is known to be initialized, read, written, raised, handled, called, or aborted, depending on the entity's class. Some combinations give an extra useful message (for example, a variable which is initialized and read but not written will produce a "could be declared constant" message). Variables of an access type and variables of an array type whose components are of an access type (or arrays of an access type, etc.) are always considered initialized, since they are initialized to 'null' by the compiler. Variables that cannot be assigned to (i.e. variables of an array type with some null dimension, or variables of a discrete type whose range includes no values) are specially recognized as "pseudo-constants": there is no message that they are not written to (since it is not possible), but there is an indication that they are pseudo-constants. The subrules "procedure" and "function" check only regular subprograms, not protected ones. On the other hand, the subrule "protected" controls all calls to any protected subprogram or entry. Exceptions raised by calling 'Raise_Exception' and tasks aborted by calling 'Abort_Task' are properly recognized as exceptions being raised and tasks being aborted, respectively. In the case of entities declared in generic packages, the rule will report on usage of the entities for each instantiation, as well as on global usage for the generic itself. Usage for an instantiation will include usage in the generic itself (i.e. if the generic writes to a variable, the variable will be marked as "written" for each instantiation). Usage for the generic itself is the union of all usages in all instantiations (i.e., if a variable from any instantiation is written to, the variable from the generic will be marked as written). Therefore, if the rule reports that a variable in a generic package can be declared constant, it means that no instance of this variable from any instantiation is being written to. But bear in mind that this can be trusted only if all units from the program are analyzed. *Note limitation::. Note that usage of entities whose declaration is not processed (like, typically, elements declared in standard packages like 'Ada.Text_IO'), is not reported. For the same reason, it is not possible to control usage of predefined operators (since they have no declaration). Ex: -- No variable in package spec; check usage otherwise Package_Variable: check usage (variable, from_spec); Constantable : search usage (variable, not from_spec, read, initialized, not written); Uninitialized : check usage (variable, not from_spec, read, not initialized, not written); Removable : search usage (object, not from_spec, not read); -- Check exceptions that are never raised -- generics that are never instantiated -- and protected objects that are never called check usage (exception, not raised); check usage (generic, not instantiated); check usage (protected, not called); -- Find how many tasks are declared, and report those -- that may be aborted count usage (task); check usage (task, aborted); 5.65.3 Tips ----------- Constants that are never used, exceptions that are never raised or handled, tasks that are never called, etc. are suspicious. Moreover, some useful compiler warnings (like those about variables that should be declared constants) are not output for variables declared in library packages, and even in some other contexts (at least with GNAT). This rule can check these kind of things, project wide. Some of these checks make sense only for entities declared in package specifications; for example, variables are often discouraged in package specifications, or need at least some extra control. That's why it can be useful to restrict some checks to package specifications. Note that an unspecified parameter in a rule stands for two rules (positive and negative form of the missing parameter). I.e.: search usage (variable, from_spec, read, written); is the same as: search usage (variable, from_spec, read, written, initialized); search usage (variable, from_spec, read, written, not initialized); Therefore, the following example will complain on the second line that the rule has already been given for this combination of parameters: search usage (variable, from_spec, read, written); search usage (variable, from_spec, read, written, not initialized); Note that the notion of constants for this rule includes named numbers. 5.65.4 Limitations ------------------ The report of this rule is output at the end of the run, and is meaningful only for the units that have been processed; i.e., if it reports "variable not read", it should be understood as "not read by the units given". In order to have meaningful results, it is therefore advisable to use this rule on the complete closure of the program. An exception can be raised by passing its ''Identity' to a procedure that will in turn call 'Raise_Exception' (and similarly for 'Abort_Task'). These cases are not statically determinable, and therefore not recognized by AdaControl. However, these cases can be identified by searching the use of the ''Identity' attribute with the following rule: check entity (all 'Identity); If an object is the prefix of a ''Access', ''Unchecked_Access', or ''Address' attribute, it can be used through the access (or address) value in ways that are not statically analyzable. The same happens if objects are targets of dynamic renamings. Such cases are detected by the rule "uncheckable". *Note Uncheckable::. Due to a weakness of the ASIS standard, it is not possible to know the mode (in, out) of variables used as parameters of dispatching calls. Such variables are considered to be read and written at the point of the call, therefore possibly creating false positives (which is safer than false negatives). Use of such constructs is detected by the rule "uncheckable". *Note Uncheckable::.  File: adacontrol_ug.info, Node: Use_Clauses, Next: With_Clauses, Prev: Usage, Up: Rules reference 5.66 Use_Clauses ================ This rule controls usage of 'use' clauses. 5.66.1 Syntax ------------- use_clauses [([,] {, })]; ::= package | local | global | type | type_local | type_global 5.66.2 Action ------------- The rule controls every 'use' or 'use type' clause, except those that name one of the mentioned packages/types. It is therefore possible to allow 'use' or 'use type' clauses just for certain packages/types. If the keyword "package" is given (or no keyword at all), all package 'use' clauses are controlled. If the keyword "global" is given, only 'use' clauses that appear in context clauses (i.e. together with the 'with' clauses) are controlled; if the keyword "local" is given, only 'use' clauses that appear as declarations are controlled. If the keyword "type" is given, all 'use type' clauses are controlled. If the keyword "type_global" is given, only 'use type' clauses that appear in context clauses (i.e. together with the 'with' clauses) are controlled; if the keyword "type_local" is given, only 'use type' clauses that appear as declarations are controlled. This rule can be given at most once for each of check, search and count. This way, it is possible to have a level considered a warning (search), and one considered an error (check). Ex: -- Global use clauses are disallowed, local ones only for IO: check use_clauses (global); check use_clauses (local, Ada.Text_IO, Ada.Wide_Text_IO); -- No use type in context clauses, count types that are "use type"'d check (type_global); count (type);  File: adacontrol_ug.info, Node: With_Clauses, Prev: Use_Clauses, Up: Rules reference 5.67 With_Clauses ================= This rule controls 'with' clauses that should be removed or moved to a better place. 5.67.1 Syntax ------------- with_clauses [( [, ])]; ::= multiple_names | reduceable | inherited 5.67.2 Action ------------- The parameters are subrule keywords that determine which kind of control is performed: * 'multiple_names' controls any 'with' clause that mentions more than one unit name. * 'reduceable' reports: * Redundant 'with' clauses, i.e. clauses given more than once for the same unit. This includes the case where the same 'with' clause is given in a specification and the corresponding body, and the case of renamings of a same unit (i.e. 'Text_IO' and 'Ada.Text_IO'). Note that giving a 'with' clause in a unit, and repeating it in a child unit (or subunit) is not considered redundant. * Unused 'with' clauses, i.e. when nothing from the withed unit is referenced in the corresponding unit. The rule signals when a withed unit is not used in a unit, but used in one or more of its subunits. If an unused 'with' clause is given on a package specification, the message reminds that it migh be useful for child units. * Moveable 'with' clauses, i.e. when the withed unit is not used in the specification, but only in the body, and should be moved to the body, or when the withed unit is only used in the private part, and could be replaced by a 'private' 'with'. * 'inherited' controls child units and subunits that reference a unit which is not directly withed, i.e. when withed only from a parent (or enclosing) unit. Although Ada rules imply that a 'with' clause carries on to child units and subunits, it can be considered better practice to ensure that every compilation unit withes directly the units it needs. Each of the keywords can be given at most once. If no keyword is given, both 'reduceable' and 'inherited' are assumed. Ex: check with_clauses (multiple_names, reduceable); search with_clauses (inherited); 5.67.3 Variables ---------------- Variable Values Default Effect Check_Private_Withoff/on on if you are working in pure Ada 95, you may not want messages that a 'with' can be replaced with a 'private' 'with'. Setting this variable to off disables these messages. Ignore_Use_Clauseoff/on on Normally, package names appearing in use clauses are not considered. Setting this variable to off will result in them being treated like any other identifier (see tip below). 5.67.4 Tips ----------- A 'with' clause can safely be removed if it is unused, and no child unit (or subunit) reports that the unit is inherited. Normally, use of a package name in a 'use' clause is not considered a usage of the package; clearly, the 'with' clause can (and should) be removed (or moved) if the only use of the package is in 'use' clauses (removing or moving the 'use' clauses by the same token). However, some programming rules may require placing 'use' clauses in certain places, forcing the corresponding 'with' clause. Set the variable 'Ignore_Use_Clause' to 'off' to make sure that a 'use' clause does mark the 'with' clause as necessary.  File: adacontrol_ug.info, Node: Examples of using AdaControl for common programming rules, Next: Specifying an Ada entity name, Prev: Rules reference, Up: Top 6 Examples of using AdaControl for common programming rules *********************************************************** In most projects, there are programming rules that define the way a program should be written. AdaControl performs controls, i.e. it finds occurrences of certain kinds of constructs. In this chapter, we give examples of commonly found programming rules, and how the corresponding controls can be written. * Menu: * Migrating from Gnatcheck:: * Rules files provided with AdaControl:: * Automatically checkable rules:: * Rules that need manual inspection::  File: adacontrol_ug.info, Node: Migrating from Gnatcheck, Next: Rules files provided with AdaControl, Prev: Examples of using AdaControl for common programming rules, Up: Examples of using AdaControl for common programming rules 6.1 Migrating from Gnatcheck ============================ The file 'gnatcheck.aru' in directory 'rules' gives the AdaControl equivalents of rules checked by Gnatcheck. This version of AdaControl covers most of Gnatcheck rules. For rules where Gnatcheck requires a parameter, the AdaControl rule is given for the default value, or with an example value. Small differences in semantics are indicated by a comment that starts with "Difference:". This file is not intended to be used directly, but as an example on how to convert Gnatcheck rules into AdaControl rules. Note that in many cases, AdaControl is much more general than Gnatcheck. The file follows as strictly as possible the rules as defined by Gnatcheck, but if you are migrating from Gnatcheck to AdaControl, you may want to use the more powerful forms provided by AdaControl.  File: adacontrol_ug.info, Node: Rules files provided with AdaControl, Next: Automatically checkable rules, Prev: Migrating from Gnatcheck, Up: Examples of using AdaControl for common programming rules 6.2 Rules files provided with AdaControl ======================================== The 'rules' directory provides also rules files that can be sourced to enforce some commonly encountered general rules. Identifiers from Standard shall not be redefined Use file 'no_standard_entity.aru'. Identifiers from System shall not be redefined Use file 'no_system_entity.aru'. Predefined IO packages shall not be used Use file 'no_io.aru'. Standard package XXX shall not be used File 'no_standard_unit.aru' controls usage of all standard packages. Comment out those that you do want to allow. Obsolescent features shall not be used Use file 'no_obsolescent_features.aru'. Not all obsolescent features are controlled, but most of them (those that are most worth checking) are. Gnat specific attributes shall not be used Use file 'no_gnat_attribute.aru' Features from annex X shall not be used Use file 'no_annex_X.aru'. The Ravenscar profile shall be enforced Use file 'ravenscar.aru'. Note that not all of the restrictions of the Ravenscar profile are currently controlled, but many are, and we expect later releases of AdaControl to increase the number of controlled features. In some cases (like "Detect_Blocking"), AdaControl does a better job than the profile, since it can detect statically situations that the profile only requires to be detected at run-time. The rule file is also slightly more restrictive than the profile; for example, the restriction "no_task_allocation" only disallows task allocators, while this rule file controls the declaration of access types on tasks. NASA coding guidelines shall be enforced Use file 'nasa.aru'. This file is an example of how to convert guidelines (available from ) into an AdaControl rules file. Ada 83 unit names shall not be used (i.e. use 'Ada.Text_IO', not 'Text_IO') Use file 'no_83_unit_name.aru'. New reserved words of Ada 2005/2012 shall not be used Use file 'reserved_2005.aru'. (the file name mentions only 2005, but it checks also for 2012 - after all, there is only one extra reserved word). Measurements for the SQALE method AdaControl can provide measurements required by the SQALE quality measurement method. The corresponding file is 'SQALE.aru'. For information about the SQALE method, please refer to J-P Rosen's paper at  File: adacontrol_ug.info, Node: Automatically checkable rules, Next: Rules that need manual inspection, Prev: Rules files provided with AdaControl, Up: Examples of using AdaControl for common programming rules 6.3 Automatically checkable rules ================================= Below are examples of rules that can be directly checked by AdaControl. Goto statement shall not be used check statements (goto); Functions shall not have 'out' or 'in out' parameters (Ada 2012) check parameter_declarations (out_parameters, max 0, function); check parameter_declarations (in_out_parameters, max 0, function); Short circuit forms should be preferred over corresponding logical operators Use_Short_Circuit: search expressions (and, or); Aggregates should be used for full assignments to structured variables, unless it is a record with a single component check multiple_assignments (groupable, given 2, ratio 100); All loops that contain exit statements must be named, and the name must be given in the exit statement check statements (unnamed_loop_exited); check statements (unnamed_exit); All type names must start with "T_" check naming_convention (type, "^T_"); All program units must repeat their name after the "end" check style (no_closing_name); Pragma Suppress is not allowed check pragmas (suppress); Ada tasking must not be used check declarations (task); "=" and "/=" shall not be used between real types check expressions (real_equality); All tasks must provide an exception handler that calls "Failure" in the case of an unhandled exception check exception_propagation (task); check silent_exceptions (failure); Unchecked_Conversion shall not be used check entities (ada.unchecked_conversion); No global variable shall be declared in the visible part of a package specification check usage (variable, from_spec); Predefined numeric types of the language shall not be used check entities (standard.Integer, standard.short_integer, standard.long_integer, standard.Float, standard.short_float, standard.long_float); Access to subprograms shall not be used check declarations (access_to_sp); Abort statements shall not be used check statements (abort); There shall be only one instantiation of Ada.Numerics.Generic_Elementary_Functions for each floating point type -- Put a --##RULE LINE OFF GEF -- for the one which is allowed GEF: check Instantiations (Ada.Numerics.Generic_Elementary_Functions); A local item shall not hide an outer one with the same name check Local_Hiding; There shall be no IOs in exception handlers check entity_inside_exception (ada.Text_IO.put, ada.Text_IO.put_line, ada.Text_IO.get, ada.Text_IO.get_line); Note that this checks for all overloaded procedures, but only those dealing with characters and strings (those defined directly within Ada.Text_IO). If the names "get" and "put" are not used for anything else than IOs, a more general form can be given as: check entity_inside_exception (all get, all put, all get_line, all put_line); This will check that no entity with the corresponding names appear in exception handlers. Exceptions shall not be used No_Exception: check declarations (exception, handlers); No_Exception: check statements (raise); No_Exception: check entities (Ada.Exceptions); This will check that no exception is declared, no exception handler is provided, and no exception is raised, not even through the services of the package 'Ada.Exceptions'. No procedure exported to C shall propagate exceptions check exception_propagation (interface, C); There shall be no Unchecked_Conversion to or from Address check instantiations (ada.unchecked_conversion, system.address); check instantiations (ada.unchecked_conversion, <>, system.address); There shall be no use clause except for Text_IO check use_clauses(ada.text_IO); Use explicit list of values in case statements rather than "when others"if the "when others" would cover less than 10 values check Case_Statement(min_others_span, 10); If a block is more than 20 lines long, it must be named check Max_Size(unnamed_block, 20); Exceptions shall not be handled except by main program check declaration (handlers) This check will be disabled for the exception handler of the main program. Each unit has a header starting with a fixed format, and must contain at least 10 lines of comments check header_comments (model, "header.txt"); check header_comments (minimum, 10); The file 'header.txt' contains the required header (as regexps), like: ^--*{50}$ ^-- This is a header$  File: adacontrol_ug.info, Node: Rules that need manual inspection, Prev: Automatically checkable rules, Up: Examples of using AdaControl for common programming rules 6.4 Rules that need manual inspection ===================================== Below are examples of rules that require manual inspection, but where AdaControl can be used to identify suspicious areas. All usages of the 'ADDRESS attribute shall be justified and documented search entities (all 'address); Specifying an address for a variable shall be restricted to hardware interfacing search representation_clauses(address); There shall be no memory leakage search Allocators; This rule identifies all allocations, and thus can be used to check that all allocated elements are properly deallocated.  File: adacontrol_ug.info, Node: Specifying an Ada entity name, Next: Syntax of regular expressions, Prev: Examples of using AdaControl for common programming rules, Up: Top Appendix A Specifying an Ada entity name **************************************** * Menu: * General syntax:: * Overloaded names:: * Enumeration literals:: * Operators:: * Attributes:: * Anonymous constructs and extended return statements:: * Record and protected types components:: * Formals of access to subprogram types:: * Limitation::  File: adacontrol_ug.info, Node: General syntax, Next: Overloaded names, Prev: Specifying an Ada entity name, Up: Specifying an Ada entity name A.1 General syntax ================== Many rules can take Ada entities as parameters. Each time a rule uses the category , it refers to an Ada entity that can be specified with the following syntax: ::= | "all" | "all" '' is the full name of the Ada entity, using normal Ada dot notation (with some extensions, see below). Full name means that you give the full expanded name, starting from a compilation unit. This name must be the actual full name, i.e. it must not include any renaming (otherwise the name will not be recognized). For example, the usual 'Put_Line' must be given as 'Ada.Text_IO.Put_Line', not as 'Text_IO.Put_Line'. Predefined elements ('Integer', 'Constraint_Error') must be given in the form 'Standard.Integer' or 'Standard.Constraint_Error', since they are logically declared in the package 'Standard'. '' is a single identifier, possibly followed by overloading information. No qualification is allowed. '' is an attribute name, including the quote. No overloading information is allowed. '' designates a single entity or several overloaded entities declared in the same place (as identified by the prefix), while 'all ' designates all identifiers with the given name in the program, irrespectively of where they appear. 'all ' designates all occurrences of the given attribute, irrespectively of what the attribute applies to. A utility is provided with AdaControl to help you find the full name of an entity. *Note pfni::. If you are using GPS with AdaControl plug-ins, it can be accessed directly from the contextual menu. *Note Contextual menu::.  File: adacontrol_ug.info, Node: Overloaded names, Next: Enumeration literals, Prev: General syntax, Up: Specifying an Ada entity name A.2 Overloaded names ==================== In Ada, names can be overloaded. This means that you can have several procedures 'P' in package ' Pack', if they differ by the types of the parameters. If you just give the name 'Pack.P' as the , the corresponding rule will be applied to all elements named 'P' from package 'Pack'. If you want to distinguish between overloaded names, you can specify a profile after the element's name. A profile has the syntax: "{" [ ["access"] { ";" ["access"] } ] ["return" ] "}" You must specify the type name, even if the declaration uses a subtype of the type; this is because Ada uses types for overloading resolution, not subtypes. Anonymous access parameters are specified by putting 'access' in front of the type name. An overloaded name for a procedure without parameters uses just a pair of empty brackets. If the subprogram is a function, you must provide the 'return ' part for the return type of the function. The types must also be given as a unique name, i.e. including the full path: if the type is 'T' declared in package 'Pack', you must specify it as 'Pack.T'. As a convenience, the 'Standard.' is optional for predefined types, so you can write 'Standard.Integer' as 'Integer'. There is no ambiguity, since a type is always declared within some construct. Note that omitting 'Standard' works only for types that are part of the profile used to distinguish between overloaded Ada entities but that the Ada entity name must always contain Standard if it is a predefined element. Overloaded names can be also be used with the 'all ' form of the . In this case, the rule will be applied to all names that are subprograms with the given identifier and matching the given profile, irrespectively of where they appear. Note that if you use an overloaded name, all overloadable names that are part of the , including those of the profile, must use the overloaded syntax. For example, given the following program procedure P is procedure Q (I : Integer) is ... end Q; procedure Q (F : Float) is ... end Q; begin ... end P; If you want to distinguish between the two procedures 'Q', you must specify them as 'P{}.Q{Integer}' and 'P{}.Q{Float}' (note the 'P{}' which specifies an overloaded name for a procedure 'P' without parameters). The names of entities which can not be overloaded (like package, exception, ...) must not be suffixed by braces (e.g. 'Ada.Text_IO.Put_Line{Standard.String}').  File: adacontrol_ug.info, Node: Enumeration literals, Next: Operators, Prev: Overloaded names, Up: Specifying an Ada entity name A.3 Enumeration literals ======================== Following normal Ada rules, an enumeration literal is considered a parameterless function. If you want to distinguish between overloaded enumeration literals, you can use overloaded names for them. For example, given: package Pack is type T1 is (A, B); type T2 is (B, C); end Pack; Ada entities names are: * 'Pack.B{return Pack.T1}' * 'Pack.B{return Pack.T2}'  File: adacontrol_ug.info, Node: Operators, Next: Attributes, Prev: Enumeration literals, Up: Specifying an Ada entity name A.4 Operators ============= AdaControl handles operators (i.e. functions like '"+"') correctly. Of course, you must specify such operations using normal Ada syntax: if you define the integer type 'T' in package 'Pack', an overloaded name for the addition would be 'Pack."+"{Pack.T; Pack.T return Pack.T}'.  File: adacontrol_ug.info, Node: Attributes, Next: Anonymous constructs and extended return statements, Prev: Operators, Up: Specifying an Ada entity name A.5 Attributes ============== It is also possible to designate attributes of entities, using the normal notation (i.e. 'Standard.Integer'First'). If the name of an attribute which is a function appears in a name that uses the overloaded syntax, it is not necessary (and actually not allowed) to provide its profile, since there is no possible ambiguity in that case. For example, given: procedure P (I : Integer) is type T is range 1 .. 10; begin ... end P; You can designate the ''Image' attribute for type 'T' as 'P{Standard.Integer}.T'Image' (the profile of the ''Image' function is not given, as would be necessary for a normal function). To designate all occurrences of an attribute, use 'all' in front of the attribute. To designate only occurrences of an attribute whose prefix is a (sub) type (but any type or subtype), give it as 'type'Attr' (i.e. the keyword "type" is put in front of the quote). 'all' may be used in place of an attribute name to mean "any attribute". See examples below. check entities (all 'Image); -- Find all occurrences of 'Image check entities (all type'Length); -- Find all occurrences of 'Length -- applied to a type check entities (Standard.Integer'all); -- Find all attributes applied -- to type Integer Check entities (all type'all); -- Find all attributes applied -- to a type check entities (all 'all); -- Find all attributes  File: adacontrol_ug.info, Node: Anonymous constructs and extended return statements, Next: Record and protected types components, Prev: Attributes, Up: Specifying an Ada entity name A.6 Anonymous constructs and extended return statements ======================================================= There is a special case for elements that are defined (directly or indirectly) within unnamed loops or block statements. Everything happens as if the unnamed construct was named '_anonymous_'. Therefore if you have the following program: procedure P is begin for I in 1..10 loop declare J : Integer; begin ... end; end loop; end P; You can refer to 'I' as 'P._anonymous_.I', and to 'J' as 'P._anonymous_._anonymous_.J'. Similarly, an extended return statement is considered "named" 'return'. Therefore if you have the following program: function F return Integer is I : Integer; begin return I : Integer do ... end return; end F; You can refer to the 'I' declared in 'F' as 'F.I', and to the return object 'I' as 'F.return.I'.  File: adacontrol_ug.info, Node: Record and protected types components, Next: Formals of access to subprogram types, Prev: Anonymous constructs and extended return statements, Up: Specifying an Ada entity name A.7 Record and protected types components ========================================= You can designate the name of a record or protected type component (a "field" name), but to identify it uniquely, you must precede its name by the name of the type. This is a small extension to Ada syntax, but it is the simplest and most natural way to deal with this case. For example, given: procedure P is type T is record Name : Integer; end record; ... The Ada entity name is 'P.T.Name'.  File: adacontrol_ug.info, Node: Formals of access to subprogram types, Next: Limitation, Prev: Record and protected types components, Up: Specifying an Ada entity name A.8 Formals of access to subprogram types ========================================= Similarly, you can designate the formal of an access to subprogram type by prefixing it by the access type. For example, given: procedure P is type T is access procedure (X : Integer); ... The Ada entity name of the formal is 'P.T.X'.  File: adacontrol_ug.info, Node: Limitation, Prev: Formals of access to subprogram types, Up: Specifying an Ada entity name A.9 Limitation ============== Due to a limitation of ASIS for GNAT, it is not possible to specify a profile with predefined operators; predefined operators without a profile work normally. -- This will not recognize "<" on Standard.Integer: check entities (Standard."<"{Standard.Integer, Standard.Integer return Standard.Boolean}); -- This will correctly recognize all predefined "<": check entities (Standard."<");  File: adacontrol_ug.info, Node: Syntax of regular expressions, Next: Non upward-compatible changes, Prev: Specifying an Ada entity name, Up: Top Appendix B Syntax of regular expressions **************************************** The following syntax gives the complete definition of regular expressions, as used by several rules. It is taken from the specification of the package 'gnat.regpat', where additional information is available. regexp ::= expr ::= ^ expr -- anchor at the beginning of string ::= expr $ -- anchor at the end of string expr ::= term ::= term | term -- alternation (term or term ...) term ::= item ::= item item ... -- concatenation (item then item) item ::= elmt -- match elmt ::= elmt * -- zero or more elmt's ::= elmt + -- one or more elmt's ::= elmt ? -- matches elmt or nothing ::= elmt *? -- zero or more times, minimum number ::= elmt +? -- one or more times, minimum number ::= elmt ?? -- zero or one time, minimum number ::= elmt { num } -- matches elmt exactly num times ::= elmt { num , } -- matches elmt at least num times ::= elmt { num , num2 } -- matches between num and num2 times ::= elmt { num }? -- matches elmt exactly num times ::= elmt { num , }? -- matches elmt at least num times non-greedy version ::= elmt { num , num2 }? -- matches between num and num2 times non-greedy version elmt ::= nchr -- matches given character ::= [range range ...] -- matches any character listed ::= [^ range range ...] -- matches any character not listed ::= . -- matches any single character -- except newlines ::= ( expr ) -- parens used for grouping ::= \ num -- reference to num-th parenthesis range ::= char - char -- matches chars in given range ::= nchr ::= [: posix :] -- any character in the POSIX range ::= [:^ posix :] -- not in the POSIX range posix ::= alnum -- alphanumeric characters ::= alpha -- alphabetic characters ::= ascii -- ascii characters (0 .. 127) ::= cntrl -- control chars (0..31, 127..159) ::= digit -- digits ('0' .. '9') ::= graph -- graphic chars (32..126, 160..255) ::= lower -- lower case characters ::= print -- printable characters (32..127) ::= punct -- printable, except alphanumeric ::= space -- space characters ::= upper -- upper case characters ::= word -- alphanumeric characters ::= xdigit -- hexadecimal chars (0..9, a..f) char ::= any character, including special characters ASCII.NUL is not supported. nchr ::= any character except \()[].*+?^ or \char to match char \n means a newline (ASCII.LF) \t means a tab (ASCII.HT) \r means a return (ASCII.CR) \b matches the empty string at the beginning or end of a word. A word is defined as a set of alphanumerical characters (see \w below). \B matches the empty string only when *not* at the beginning or end of a word. \d matches any digit character ([0-9]) \D matches any non digit character ([^0-9]) \s matches any white space character. This is equivalent to [ \t\n\r\f\v] (tab, form-feed, vertical-tab,... \S matches any non-white space character. \w matches any alphanumeric character or underscore. This include accented letters, as defined in the package Ada.Characters.Handling. \W matches any non-alphanumeric character. \A match the empty string only at the beginning of the string, whatever flags are used for Compile (the behavior of ^ can change, see Regexp_Flags below). \G match the empty string only at the end of the string, whatever flags are used for Compile (the behavior of $ can change, see Regexp_Flags below). ... ::= is used to indication repetition (one or more terms) Embedded newlines are not matched by the ^ operator. It is possible to retrieve the substring matched a parenthesis expression. Although the depth of parenthesis is not limited in the regexp, only the first 9 substrings can be retrieved. The operators '*', '+', '?' and '{}' always match the longest possible substring. They all have a non-greedy version (with an extra ? after the operator), which matches the shortest possible substring. For instance: regexp="<.*>" string="

title

" matches="

title

" regexp="<.*?>" string="

title

" matches="

" '{' and '}' are only considered as special characters if they appear in a substring that looks exactly like '{n}', '{n,m}' or '{n,}', where n and m are digits. No space is allowed. In other contexts, the curly braces will simply be treated as normal characters. Note that if you compiled AdaControl with the 'String_Matching_Portable' package, only basic wildcards are available, i.e. only "*" and "?" are supported, where "*" matches any string of character and "?" matches a single character.  File: adacontrol_ug.info, Node: Non upward-compatible changes, Prev: Syntax of regular expressions, Up: Top Appendix C Non upward-compatible changes **************************************** This chapter is intended to users of a previous version of AdaControl, who want to migrate rule files to the latest version. Although we understand the burden of non upward-compatible changes, we consider that making AdaControl more powerful and easier to use is sometimes more important than strict compatibility. Moreover, in most cases the changes are very straightforward and can be done easily by hand, or with scripts if many files are involved. C.1 Migrating from 1.16r11 ========================== C.1.1 Declarations, Entities, Instantiations -------------------------------------------- These rules use the concept of "location" to restrict the places where some constructs are controlled. It is now possible to specify "not" in front of a location keyword. As a consequence, the keyword "nested" has been removed, as it was the same thing as "not library". In short, change: check declarations (nested procedure); to: check declarations (not library procedure); C.2 Migrating from 1.15r5 ========================= C.2.1 Array_Declarations ------------------------ The extension of aspects to more rules required a slight change in the syntax of the "component" subrule: the keywords "packed", "sized", and "component_sized" have been changed to "pack", "size", and "component_size", respectively. C.2.2 Multiple_Assignments -------------------------- Due to new functionalities, and expecting more in the future, the rule has been renamed to "Assignments". C.2.3 No_Operator_Usage ----------------------- The syntax has been changed, due to the introduction of "indexing". Moreover, the rule was not consistent, in that the result of "none" was affected by the presence or absence of "logical" (without "logical", "none" included all types, while with it, it counted only those not counted with "logical"). If you want that exact same behaviour (which might not be desirable), change: -- (1) check no_operator_usage (none); -- (2) check no_operator_usage (logical); -- (3) check no_operator_usage (none, logical) -- or no parameters to: -- (1) check no_operator_usage(ignore indexing, ignore logical); -- or no parameters -- (2) check no_operator_usage (logical); -- (3) check no_operator_usage (not logical), check no_operator_usage (logical); C.2.4 Object_Declarations ------------------------- Due to the necessity of avoiding a syntactic ambiguity in the new subrule "type", the keyword "all" is no more allowed in the syntax for the subrule "min_integer_span" (specifying neither "variable" or "constant" still means the subrule applies to both, as before). Change: count object_declarations (min_integer_span, all 8); to: count object_declarations (min_integer_span, 8); C.2.5 Statements ---------------- The subrule "exit" was documented as controlling all exit statements, but it did not report exits from 'for' and 'while' loops if "exit_for_loop" (respectively "exit_while_loop") was also specified. It now behaves as documented, i.e. it controls all 'exit' statements. Note that if you want separate messages for each kind of loop, the new rule "exit_plain_loop" controls exit from plain loops. C.2.6 Style ----------- The subrule "positional_association" is now a rule of its own, "positional_associations". The order of parameters is different, due to various subrules of the new rule. Typically, change: check style (parameter_association, call, 1); to: check parameter_associations (all, 1, call); Note that the new rule distinguishes between regular array aggregates and aggregates used for enumeration representation clauses. Modes of the subrules "parameter_order" and "formal_parameter_order" are now separated by "|". With the previous syntax, forgetting a comma was changing the meaning of the rule without introducing a syntax error. Typically, change: check style (parameter_order, in defaulted_in, out in_out); to: check style (parameter_order, in | defaulted_in, out | in_out); C.3 Migrating from 1.14r9 ========================= C.3.1 Local_Hiding ------------------ Due to the introduction of extra parameters for allowed patterns, it is no more possible to specify the rule several times in the same command. Change: check local_hiding (strict, overloading); to: check local_hiding (strict); check local_hiding (overloading); The special subrule "overloading_short" has been replaced by a rule variable to choose the report format. Change: check local_hiding (overloading_short); to: set local_hiding.overloading_report compact; check local_hiding (overloading); C.3.2 Max_Nesting ----------------- The value given is now the nesting level (consistent with the rule name), no more the maximum depth. This is more natural (Max_Nesting(1) means that the construct can be nested once), but it is one less than in previous versions. For example, change: check Max_Nesting (5); to: check Max_Nesting (4); C.3.3 Parameter_Declarations ---------------------------- The subrules have been generalized, using the same syntax for bounds as other rules. Change: check parameter_declarations (min_parameters, 1); check parameter_declarations (max_parameters, 5); check parameter_declarations (max_defaulted_parameters, 3); to: check parameter_declarations (all_parameters, min 1, max 5); check parameter_declarations (defaulted_parameters, max 3); C.4 Migrating from 1.11r4 ========================= C.4.1 Expressions ----------------- The subrule 'Real_Equality' does not control user-defined equality operators any more. This is intended to be more of an improvement than an incompatibily. C.4.2 Special_Comments ---------------------- Since the number of subrules is growing, and do not only address 'special" comments, this rule has been renamed to "comments". C.5 Migrating from 1.10r10 ========================== C.5.1 GPS integration --------------------- Due to a bug/feature of the GPS interface, if a units file was specified, it did not reappear later in the corresponding box of the Switch/AdaControl dialog. This has been fixed, but you must reenter the units file name in the dialog. C.5.2 Representation_Clauses ---------------------------- The introduction of categories made some subrules syntactically ambiguous or redundant. In consequence, the subrules "derived_record", "extension_record", and "tagged_record" have been removed, and the subrules "record", "incomplete_record", and "non_contiguous_record" have been renamed as "layout", "incomplete_layout", and "non_contiguous_layout" respectively. Change: check representation_clause (derived_record); check representation_clause (extension_record); check representation_clause (tagged_record); check representation_clause (record); check representation_clause (incomplete_record); check representation_clause (non_contiguous_record); to: check representation_clause (new layout); check representation_clause (extension layout); check representation_clause (tagged layout); check representation_clause (layout); check representation_clause (incomplete_layout); check representation_clause (non_contiguous_layout); C.6 Migrating from 1.9r4 ======================== C.6.1 Array_Declarations ------------------------ The subrule "Max_Length" has been changed to "Length", with the possibility to specify both min and max values. Change: check array_declarations (max_length, 100); to: check array_declarations (length, max 100); C.6.2 Declarations ------------------ The subrule names "initialized_record_field", "uninitialized_record_field", "initialized_protected_field", and "uninitialized_protected_field" have been changed to "initialized_record_component", "uninitialized_record_component", "initialized_protected_component", and "uninitialized_protected_component", respectively, to be more consistent with official Ada terminology. Change: check declarations (initialized_record_field, uninitialized_record_field, initialized_protected_field, uninitialized_protected_field); to: check declarations (initialized_record_component, uninitialized_record_component, initialized_protected_component, uninitialized_protected_component); The subrule "aliased" has been split into "aliased_constant" and "aliased_variable". The old rule controlled both at the same time, but did not control aliased components (there are now other subrules to that effect). Change: check declarations (aliased); to: check declarations (aliased_constant, aliased_variable); C.6.3 Default_Parameter ----------------------- The is no more allowed to be "all", because it was ambiguous with the "all " syntax of . If you used "all", duplicate the control with "calls" and "instantiations". Change: My_label : check default_parameter (all, ...); to: My_label : check default_parameter (calls, ...), check default_parameter (instantiations, ...); C.6.4 Improper_Initialization ----------------------------- By default, variables declared directly within (generic) package specifications and bodies are no more checked. To get the previous behaviour, add the "package" modifier. Change: check improper_initialization (variable); to: check improper_initialization (package variable); C.7 Migrating from 1.8r8 ======================== C.7.1 CSV(X) format ------------------- If the output format is CSV or CSVX, the file name, line number and column number are generated as three different spreadsheet columns, instead of forming a single message. This makes it easier to use a spreadsheet program for per-file statistics. C.7.2 Default_Parameter ----------------------- Due to the introduction of the "positional" keyword, "not used" is now spelled "not_used". Change: check default_parameter (proc, param, not used); to: check default_parameter (proc, param, not_used); C.7.3 Other_Dependencies ------------------------ This rule has been changed into a subrule of the (new) rule "Dependencies". Change: check Other_Dependencies (pack1, pack2); to: check Dependencies (others, pack1, pack2); C.7.4 Special_Comments ---------------------- Due to the introduction of another subrule, add "pattern" as the first parameter to the rule. Change: check Special_Comments ("TBSL"); to: check Special_Comments (pattern, "TBSL"); C.7.5 Statements ---------------- The "raise" subrule now reports all occurrences of the 'raise' statement, even if another control is applicable to the same statement. The "reraise" subrule now reports calls to 'Ada.Exceptions.Reraise_Occurrence'. The "raise_standard" subrule now reports exceptions raised by calls to 'Ada.Exceptions.Raise_Exception'. C.8 Migrating from 1.7r9 ======================== C.8.1 Case_Statement -------------------- This rule now allows the specification of both min and max values for each subrule. Subrule names have been changed accordingly. Change: check Case_Statement (max_range_span, 5); check Case_Statement (max_values, 10); check Case_Statement (min_others_span, 4); check Case_Statement (min_paths, 6); to: check Case_Statement (range_span, max 5); check Case_Statement (values, max 10); check Case_Statement (others_span, min 4); check Case_Statement (paths, min 6); C.8.2 Max_Parameters -------------------- This rule has been changed into a subrule of the (new) rule "Parameter_Declarations". Change: check Max_Parameters (10); to: check Parameter_Declarations (Max_Parameters, 10); C.9 Migrating from 1.6r8 ======================== C.9.1 "message" command ----------------------- The message is now syntactically a string, and must always be enclosed in double quotes (quotes were optional in previous versions). C.9.2 "source" command ---------------------- If a "source" command is given in a rules file, and the sourced file is given with a relative path, it is interpreted relatively to the sourcing file (it was interpreted relatively to the current directory previously). This should make "chained" sourcing easier, since the interpretation does not depend on where the sourcing file is being called from. C.9.3 Control_Characters ------------------------ This rule is now called "Characters" and can process other kinds of characters in addition to control characters. Control characters correspond to the "control" parameter of the rule. Change: check control_characters; to: check characters (control); C.9.4 If_For_Case ----------------- This rule has been changed into a subrule of the (new) rule "simplifiable_statements". Change: check if_for_case; to: check simplifiable_statements (if_for_case); C.9.5 Instantiations -------------------- The rule does not print the number of instantiations any more, since the same effect can be achieved with the "count" control kind. C.9.6 Local_Instantiation ------------------------- This rule has been removed, since its effect can now be achieved with other rules: the rule "declarations" to check for local instantiations of any generic, and the rule "instantiations" to check for local instantiations of specified generics. Change: R1: check Local_Instantiation; R2: search Local_Instantiation (Ada.Unchecked_Conversion); to: R1: check declarations (local instantiation); R2: search Instantiations (local Ada.Unchecked_Conversion); C.9.7 Naming_Convention ----------------------- Quotes are no more optional around patterns. The modifier is now before the (it was before the pattern previously). This may require splitting the rule in two in some cases. For example, change: check naming_convention (object, local "^L_", global "^G_"); to: check naming_convention (local object, "^L_"); check naming_convention (global object, "^G_"); C.9.8 No_Safe_Initialization ---------------------------- The name of this rule has been changed to "improper_initialization", since it now controls other cases of improper initialization. C.9.9 Special_Comments ---------------------- Quotes are no more optional around patterns. C.9.10 Statements ----------------- Two subrules of this rule have migrated to the new rule "simplifiable_statements" (with slightly different names). Change: check statements (unnecessary_null); check statements (while_true); to: check simplifiable_statements (null); check simplifiable_statements (loop); C.10 Migrating from 1.5r24 ========================== C.10.1 Declarations ------------------- The subrule "Formal_In_Out" has been renamed as "In_Out_Generic_Parameter", for consistency with the new "In_Out_Parameter" subrule. The subrules "renames" and "not_operator_renames" have been renamed to "renaming" and "not_operator_renaming". As a consequence of being able to specify the location of any construct, the subrules "nested_function_instantiation", "nested_generic_function", "nested_generic_package", "nested_generic_procedure", "nested_package", "nested_package_instantiation", and "nested_procedure_instantiation" have been removed and replaced with the corresponding general construct (without "nested_"). You can have the same effect by specifying the "nested" modifier in front of them. I.e., change: check declarations (nested_generic_function); to: check declarations (nested generic_function); C.10.2 Naming_Convention ------------------------ The keyword is placed before the keyword instead of before the , which looks more natural. The "Any" keyword has been removed, since omitting the keyword has the same effect. Change: check naming_convention (variable, global "^G_"); check naming_convention (package, any "^Pack_"); to: check naming_convention (global variable, "^G_"); check naming_convention (package, "^Pack_"); C.10.3 Non_Static_Constraint ---------------------------- This rule is now called Non_Static, since it is no more restricted to constraints. The parameters "index" and "discriminant" have been changed to "index_constraint" and "discriminant_constraint", respectively. Change: check non_static_constraint (index, discriminant); to: check non_static (index_constraint, discriminant_constraint); C.10.4 Positional_Parameters ---------------------------- This rule has been renamed to 'Insufficient_Parameters', since it does no more handle the "maximum" subrule. Controlling positional parameters according to their number is now done by the rule 'style (positional_association)'. Change: check positional_parameters (maximum, 3); check positional_parameters (insufficient, 2, Boolean); to: check style (positional_association, call, 3); check insufficient_parameters (2, Boolean); C.10.5 Real_Operator -------------------- This rule is no more a rule of its own, it is a subrule of the (new) rule Expressions, whose name is Real_Equality. Change: check Real_Operators; to: check expressions (Real_Equality); C.10.6 Style ------------ The name of the subrule "casing" has been changed to "casing_identifier" since the casing of attributes and pragmas can now also be checked. The casing style is no more optional. The name of the subrule "literal" has been changed to "numeric_literal" (since characters and strings are also literals, but are not handled by this subrule). The subrule "exposed_literal" now requires an extra parameter to tell whether it applies to integer literals, real literals, character literals or string literals. Allowed values are provided after this parameter, and must of course be of the appropriate type. In short, if you had: check style (exposed_literal, 0, 1, 0.0, 1.0); you must change it to: check style (exposed_literal, integer, 0, 1) check style (exposed_literal, real, 0.0, 1.0); The "aggregate" parameter of the subrule "positional_association" has been split into "array_aggregate" and "record_aggregate". For example, change: check style (positional_association, aggregate); into: check style (positional_association, record_aggregate, array_aggregate); C.11 Migrating from 1.4r20 ========================== C.11.1 GPS integration ---------------------- The XML file used to describe AdaControl features to GPS used to be called 'adactl.xml'. It is now called 'zadactl.xml', since GPS processes its initialization files in alphabetical order. This avoids shuffling the menus when AdaControl support is activated. Make sure to remove the old 'adactl.xml' file from the GPS plug-ins directory before installing the new version. C.11.2 Declarations ------------------- The parameters "access" and "access_subprogram" have been changed to "access_type" and "access_subprogram_type", for consistency with the new parameters. C.11.3 Header_Comments ---------------------- A keyword has been added to specify the required number of comment lines. Change: check Header_Comments (10); to: check Header_Comments (minimum, 10); C.11.4 No_Closing_Name ---------------------- This rule is now part of the "style" rule. Change: check|search|count No_Closing_Name; to: check|search|count Style (No_Closing_Name); C.11.5 Specification_Objects ---------------------------- This rule is now part of the "usage" rule. Change: check|search|count Specification_Objects (); to: check|search|count Usage (Object, From_Spec, ); C.11.6 Statement ---------------- Name changed from "statement" to "statements" (added an 's'), to be consistent with other rules. C.11.7 When_Others_Null ----------------------- This rule is now part of the "statements" rule. Change: check|search|count When_Others_Null (case); check|search|count When_Others_Null (exception); to: check|search|count Statements (case_others_null); check|search|count Statements (exception_others_null); adactl-1.17r3/doc/adacontrol_pm.txt0000644000175000017510000013454712621403304016440 0ustar rosenadalogAdaControl Programmer Manual **************************** Last edited: November 13, 2015 This is the AdaControl Programmer Manual. It is intended for those who want to add new rules to AdaControl, or more generally modify (and presumably improve!) AdaControl. Reading this manual is not necessary to use AdaControl. On the other hand, it is assumed that the reader is familiar with how to use AdaControl. Commercial support is available for AdaControl. If you plan to use AdaControl for industrial projects, or if you want it to be customized or extended to match your own needs, please contact Adalog at info@adalog.fr. AdaControl is Copyright (C) 2005-201 Eurocontrol/Adalog, except for some specific modules that are (C) 2006 Belgocontrol/Adalog, (C) 2006 CSEE/Adalog, (C) 2006 SAGEM/Adalog, or (C) 2015 Alstom/Adalog. AdaControl is free software; you can redistribute it and/or modify it under terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This unit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License distributed with this program; see file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, if other files instantiate generics from this program, or if you link units from this program with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Public License. This document is Copyright (C) 2005-2015 Eurocontrol/Adalog. This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. 1 General ********* This programmer manual describes how to add new rules to AdaControl. Since AdaControl is based on ASIS, this manual assumes that the reader has some familiarity with ASIS programming. Modifying AdaControl needs of course a source distribution. It is OK to work with the regular source distribution, but if you intend to submit your patches, it is appropriate to get the latest "bleeding edge" version from our GIT repository on SourceForge. Instructions on how to get AdaControl from GIT are here (http://sourceforge.net/projects/adacontrol/files/download-from-git.txt/download) 1.1 vocabulary ============== Some terms have a precise definition in AdaControl, and will be used with that signification in the rest of this manual. A rule is an AdaControl package whose purpose is to recognize occurrences of certain constructs in Ada programs. All rules are children of the "Rules" package. By extension, the term rule is also used to designate the check that is performed by the package. A rule has a name, and may have parameters. A control defines a check to be performed on some Ada text. A control is defined by a rule, and the value of the parameters given to the rule. A command is a statement in the command language interpreted by AdaControl. A control command is a kind of command that describes a check to be performed. A control commmand includes a kind ("check", "search" or "count", see user's guide), and a control (rule name and parameters). A context is a set of values used by a rule to keep the characteristics associated with a control. Those values can, but need not necessarily, be the parameters of the control. 1.2 General organization ======================== The AdaControl tool includes several main components. Those that are relevant for writing new rules are: * A general framework that provides services that are necessary to write rules. This includes a special module, 'Framework.Plugs', where rules are plugged-in; * A set of utilities providing useful functionalities, but not specific to the writing of rules. Actually, the utilities packages are shared with other programs from Adalog's "Semtools" family of tools. * The rules themselves. This clear distinction makes it easy to add new rules. Actually, the framework relieves the programmer from all the "dirty work", and adding a new rule requires nothing else than caring about the rule itself. 2 The framework and utilities packages ************************************** The framework includes the package 'Framework' itself and its public child packages. There are also some private child packages, but they are of course not relevant to the users of the framework. In each package, services (declarations, subprograms) that are relevant for writing rules appear at the beginning of the package specification. Other services that are used by the rest of the framework, but not intended to be called from a rule, appear below the following comment lines: -- -- Declarations below this line are for the use of the framework -- This section provides an overview of the services that are made available by the framework and other utilities packages. It is not the purpose of this section to describe the syntax of every service provided : please refer to the comments in the specification of each package. Existing rules are also typical examples of how to use these functionnalities. 2.1 The package Adactl_Constants ================================ AdaControl has some fixed size structures that limit the complexity of the programs it can handle, like for example the maximum numbers of parameters that subprograms can have, the maximum nesting of loops, etc. These limits are set as constants in the package 'Adactl_Constants'. These values are large enough to accomodate any reasonable program, but should you hit one of these limits, you can safely change them here. No other change is required. If a rule needs to set a fixed dimension to some tables for example, it should use the constants defined in this package. If no existing constant is appropriate, add a new one to the package, don't define dimensioning constants in the rule itself. 2.2 The package Framework ========================= The package Framework includes general services, needed by most rules. These include: * The definition of some constants that are used to fix a bound to the number of allowable constructs. Use these constants to dimension tables for example. * The notion of location, with associated subprograms. A location is a place within a source file where some construct happens. * The notion of rule context. A rule context is some information that a rule associates to entities. For example, given the following rules: search Entities (Blah); Strictly_Forbidden: check entities (Ada.Unchecked_Conversion) the rule Entities must associate that 'Blah' is the target of a search, and that 'Ada.Unchecked_Deallocation' is the target of a check with label 'Strictly_Forbidden'. 2.3 The package Framework.Rules_Manager ======================================= The package 'Framework.Rules_Manager' is used to register and manage rules. The procedure 'Register' declares the name of the rule and the associated 'Help', 'Add_Control', 'Command', 'Prepare', and 'Finalize' procedures. Note that there is nothing else to do to make a rule known to the system: once it is registered, it will be recognized on the command line, help command will work, etc. The procedure 'Enter' is used to let the system know which rule is currently active. 2.4 The package Framework.Reports ================================= The package 'Framework.Reports' is used to report error or found messages when a rule matches. It deals automatically with things like rules being temporarily disabled, therefore the rule does not have to care. The main service provided by this package is the 'Report' procedure, which comes in two flavors. This is the only allowed way for a rule to report its findings, never use 'Wide_Text_IO' or any other mean. The specifications of the Report procedures are: procedure Report (Rule_Id : in Wide_String; Rule_Label : in Wide_String; Ctl_Type : in Control_Kinds; Loc : in Location; Msg : in Wide_String); procedure Report (Rule_Id : in Wide_String; Context : in Root_Context'class; Loc : in Location; Msg : in Wide_String); The first procedure expects the label and type to be given explicitely, while the second one gets them from a 'Context' object (see comments in the package). Note that there is only one string for the message. Please do not try to "improve" the presentation by introducing line breaks in the report message: the output of AdaControl should remain parseable by rather naive tools, therefore it is necessary to ensure that one output line = one message. In addition, there is an 'Uncheckable' procedure, with the following profile: procedure Uncheckable (Rule_Id : in Wide_String; Risk : in Uncheckable_Consequence; Loc : in Location; Msg : in Wide_String); This procedure is called each time a rule encounters some dynamic construct that prevents normal checking. The parameter 'Risk' is 'False_Positive' if the consequence of not being able to analyze the construct would result in wrong error messages, and 'False_Negative' if it would result in not detecting something that could be an error. It is important to call this procedure for any non-checkable construct, since it is what allows the rule "Uncheckable" to work. 2.5 The package Framework.Language ================================== The package 'Framework.Language' provides functionalities for parsing parameters, as well as the rest of the command language; but of course only the subprograms used to parse parameters are relevant to the writing of rules. The functionalities provided here allow a good deal of freedom for defining the syntax of a rule's parameters (although it is a good idea to stay as close as possible to the syntax of other rules). Look at the syntax of various rules to see what can be accomplished. The package provides a 'Parameter_Exists' function that returns 'True' if there are parameters left to parse. The kind of the next parameter can be checked with the 'Is_Integer_Parameter', 'Is_Float_Parameter', or 'Is_String_Parameter' functions. The corresponding parameter value can be retrieved with the 'Get_Integer_Parameter', 'Get_Float_Parameter', 'Get_Name_Parameter', 'Get_File_Parameter', 'Get_String_Parameter', or 'Get_Entity_Parameter' functions. The latter function returns an entity specification, i.e. a descriptor for something which is expected to be a general specification for an Ada entity (including overloading information, for example). Such an entity can be used as a key for a context. There is a generic package 'Flag_Utilities' to help manage flags (keywords) parameters defined by an enumerated type. An instantiation of this package provides a 'Get_Flag_Parameter' procedure to parse the flags, an 'Image' function to get a string representation of a flag, and a 'Help_On_Flags' function to print the help message that enumerates all possible flag values. There is a 'Get_Modifier' to process modifiers (things like "not" or "case_sensitive" in front of a parameter). For more sophisticated modifiers, you can instantiate the generic package 'Modifier_Utilities', which works like 'Flag_Utilities', but also provides the notion of sets of modifiers. Note that if you instantiate 'Flag_Utilities' or 'Modifier_Utilities' in a library package (as will be the case most of the time), you must put a 'pragma Elaborate (Framework.Language);' on top of the package. Failing to do so will result in circular elaboration problems; ('pragma Elaborate_All', as implicitely provided by GNAT, does not work). 2.6 The package Framework.Scope_Manager ======================================= The package 'Framework.Scope_Manager' provides facilities for rules that need to follow scoping rules (i.e. which identifiers are visible at a given place). It provides subprograms to query currently active scopes, and a generic package that allows associating any kind of information to a scope. Scopes are automatically managed: the information will disappear when the corresponding scope is exited, except for information associated to package specifications that will be restored when the corresponding body is entered. The scope manager follows strictly the visibility rules for child units: when entering a public child unit, the scope from the visible part of the parent is restored, and when entering the private part of the child, the scope of the private part of the parent is restored. In the case of a private child, the full scope of the parent is restored upon entering. See the package specification for more details. 2.7 The package Framework.Plugs =============================== Procedures in the package 'Framework.Plugs' are called during the traversal of the Ada source code. Unlike the rest of the framework, this package does not provide services to rules, but instead calls processing procedures defined in the rules packages. Therefore, it is necessary to plug the corresponding calls in this package. This is described in details in *note Plugging-in a new rule into the framework::. 2.8 The package Rules ===================== The package 'Rules' is (almost) empty. It's purpose is to serve as the parent package of all rules. It simply provides an empty state type ('Null_State'), and a null procedure that can be used for instantiating 'Traverse_Element' in simple cases. 2.9 The package Utilities ========================= This package provides various general facilities that are not specific to AdaControl. The main elements provided are: * 'User_Message' and 'User_Log'. Both procedures output a message, the difference being that 'User_Log' outputs its message only in verbose mode. 'User_Message' is used to print help messages. 'User_Log' could be used if some rule wanted to print some extra information in verbose mode. Note that these procedures should not be used to report the result of a check or search (use 'Framework.Reports.Report' instead). * String handling services, see package specification * Error management. The 'Error' procedure is not to be called directly, use 'Framework.Language.Parameter_Error' instead to report errors in user provided parameters. In most cases, parameters are checked in the 'Add_Control' procedure of the rule (*note Writing a new rule::), and therefore errors are reported during the parsing of the commands. In some cases, incorrect parameters are discovered while traversing the code. It is acceptable to call 'Framework.Language.Parameter_Error' at any time, but be aware that this will immediately stop all analysis. See the 'Rules.Unsafe_Paired_Calls' for an example of this. The 'Failure' procedure is used to report internal failures. It is frequent in ASIS programming to have a big case statement over the various kinds of elements, of which only a few values are interesting or possible given the context. We strongly encourage to call 'Failure' in the when others part of the case statement to trap unexpected cases. Note that the procedure is overloaded with a version that allows to print information about the failing element. * Debugging facilities. Several 'Trace' procedures allow you to output a message, possibly with a boolean value, or the context of an ASIS element or element list. There is also an 'Assert' procedure that calls 'Failure' if its condition is false; well placed 'Assert' calls are very helpfull in debugging. Note that traces are output only in debug mode. * Other facilities for managing the output that are called by the framework, but not useful for writing rules. 2.10 The packages Thick_Queries and Framework.Queries ===================================================== These packages contain high level services that are built on top of Asis queries, and can therefore be quite useful to the writing of rules. The queries are documented in the specification of the packages. The difference between the packages is that 'Thick_Queries' does not depend in any way on the other parts of AdaControl (and notably on the framework); it is therefore directly reusable for any ASIS application. On the other hand, 'Framework.Queries' requires facilities provided by the framework, and is therefore not directly reusable outside of AdaControl. 2.11 The packages Linear_Queue and Binary_Map ============================================= These packages provide simple generic containers that are needed by several rules. The generic package 'Linear_Queue' can be instantiated with any (non-limited) 'Component' type, and provides a simple queue of elements. Note that this queue has value semantics: when a queue is assigned, its content is duplicated. Queues are controlled, and therefore all internal storage allocations are internally managed. The package 'Framework.Element_Queue' is an instantiation of 'Linear_Queue' with the type 'Asis.Element'. The generic package 'Binary_Map' can be instantiated with a 'Key_Type' and a 'Value_Type', and associates values of 'Value_Type' to values of the 'Key_Type'. The mapping uses a binary tree; if you use it to keep user information, it is appropriate to rebalance the tree before starting the actual processing. *Note Prepare::. See existing rules for examples of using this package. 2.12 The package A4G_Bugs ========================= AdaControl is quite demanding on the ASIS implementation, and we found some bugs in ASIS-for-GNAT during its development. These have been reported to ACT, and are fixed in the wavefront version of GNAT, or should be fixed very soon. However, many people do not have access to the wavefront version, or prefer to stay with the stable version. This package provides replacements for some ASIS subprograms that do not behave as expected. Subprograms in this package have specifications identical to the corresponding ASIS subprograms, and are designed in such a way that there is no harm in using them with a version of ASIS that does not exhibit the bug. Therefore, it is strongly recommended to use the subprograms in this package rather than their ASIS equivalent. Note that if you run the rules file 'src/verif.aru' on your code, it will spot any use of an ASIS function for which there is a replacement in 'A4G_Bugs'. 3 Writing a new rule ******************** There are two kinds of rules: semantic rules, which operate on Ada elements, and textual rules, which operate on the source text. In some rare cases, a rule can be of both kinds at the same time; see the rule "Style" for an example of this. Note that a semantic rule can still access the text of an Ada construct with the facilities provided by the package 'Asis.Text', this does not require the rule to be 'Semantic_Textual'. All rules currently provided follow a common pattern, described below; it is recommended that new rules do the same, in order to make maintenance easier. The first thing to do before adding a new rule is to read the source for existing rules, as they provide good examples of how a rule is implemented. For an example of a simple rule, see 'Rules.Entity'; for an example of a sophisticated one, see 'Rules.Unnecessary_Use'. For an example of a textual rule, see 'Rules.Max_Line_Length'. Note that 'Rules.Entity' can be used as a template for writing new semantic rules, as most rules will follow the same general structure, just making more elaborated processing of relevant entities. 3.1 General considerations ========================== A rule is implemented as a child package of package 'Rules'. The following sections describe the structure of the specification and body of a rule package. It is good practice to use only one string type all over a program, and since ASIS is based on 'Wide_String', a rule should not use the type 'String', but rather use 'Wide_String' instead. 3.2 Specification ================= The specification of a rule package must contain the following elements: 3.2.1 Rule_ID ------------- Rule_ID is a constant of type 'Wide_String'. It is the unique rule identifier of a rule. It is used by the package 'Framework.Rules_Manager' as the key in the rules list to dispatch to the corresponding registered operation, and as the rule name used by the user on the command line to parameterize and use the rule. The name of the rule must be given in upper-case (to allow for case-independant recognition). Ex: Rule_Id : constant Wide_String := "PRAGMAS"; Note that from a language point of view, this declaration could be in the body of the package; however, for identification purposes, it is more convenient to put it in the specification. 3.2.2 Process ------------- One (or more) procedure(s) may be necessary to process the rule (collectively named the 'Process' procedures in this document). These procedures are called from 'Framework.Plugs' at appropriate places, and therefore must be declared in the specification of the rule. *Note Plugging-in a new rule into the framework::. Process procedures of a semantic rule take one parameter of type 'Asis.Element'. Although all element kinds are equivalent from the point of view of Ada's type checking, it is recommended to follow general ASIS practice, and to define the parameter with the ASIS element kind expected by the procedure. Process procedures of a textual rule take two parameters: an input line, and the corresponding location. Ex: -- Semantic rule: procedure Process_Pragma (Pragma_Element : in Asis.Pragma_Element); -- Textual rule: procedure Process_Line (Line : in Asis.Program_Text; Loc : in Framework.Location); 3.3 Body ======== It is a good habit to start the body of a rule by giving a comment explaining the general principles of the algorithm used, especially if the algorithm is not trivial. To be honest, not all current rules do provide this information, and some crucial information may be missing in the rules that do... You are more than welcome to improve these comments, especially if you think that some fundamental information should have been provided here. The body must contain a 'Help', an 'Add_Control', and a 'Command' procedure. It may also optionnally contain a 'Prepare' and a 'Finalize' procedure. These procedures are call-backs that are registered to the framework by calling 'Framework.Rules_Manager.Register' in the statements part of the body. Note that there is a parameter to this procedure that tells whether the rule is semantic, textual, or both. This procedure has 'null' defaults for the optional subprograms. 3.3.1 Help ---------- Help is a procedure that displays a short help message to the standard output for the rule. It takes no parameter. The procedure 'Help' is called when the user specifies a "-h" option for the rule. It must display a useful message by calling 'Utilities.User_Message'. In order to have a uniform presentation for all rules, the message must be structured as follows: * The word "Rule:" followed by the rule ID. * A short description of the purpose of the rule. This description can span several lines, but don't make it too long. * A blank line (call 'Utilities.User_Message' without parameter). * The word "Parameter(s):" followed by a description of parameters. Note that if you have a parameter of an enumerated type, the package 'Flag_Utilities' features a 'Help_On_Flag' procedure that formats automatically the values. If the different parameters have different meanings, you can use the form "Parameter(1):", "Parameter(2):" etc. instead. If the rule has no parameters, just say "Parameters: none". Note that the command: adactl -h all outputs the help messages for all rules, providing examples of how you should write your own help messages. Ex: procedure Help is use Utilities; begin User_Message ("Rule: " & Rule_Id); User_Message ("Control usage of specific pragmas"); User_Message; User_Message ("Parameter(s): [multiple] all | nonstandard | "); end Help; 3.3.2 Add_Control ----------------- 'Add_Control' is a procedure which is called by the rules parser when it finds a control command that refers to the corresponding rule. It is passed the corresponding label (an empty string if there is no label), and the control's kind ('Check', 'Search' or 'Count'). It will typically loop over the parameters with the various 'Get_XXX_Parameters' from package 'Rules.Language' to process the parameters. If for some reason a parameter is not appropriate to the rule, the rule should call 'Rules.Language.Parameter_Error' with an appropriate message. This procedure will raise the exception 'User_Error', and the 'Add_Control' procedure should not handle it; the exception will be processed by the framework. Note that 'Add_Control' may be called several times if the same rule is activated with different parameters in a rules file. If a rule can be specified only once, it is up to the rule to check this and call 'Parameter_Error' in case it is given more than once. Ex: procedure Add_Control (Label : in Label; Ctl_Type : in Control_Kinds) is begin while Parameter_Exists loop -- process parameter end loop; end Add_Control; There is no special requirement on the implementation of the 'Add' procedure. The programmer is free to interpret the parameters as necessary and do whatever initialisation processing they imply. Typically, for a rule that searches for the occurrence of an identifier, this procedure would add the identifier to some internal context table. 3.3.3 Command ------------- 'Command' is a procedure used by the framework to send "commands" to the rule in order to change its state. It has a parameter of an enumeration type that can take the values 'Clear', 'Suspend', and 'Resume'. * 'Clear': 'Command' is called with this value whenever a "clear" command is given. The rule must reset the rule to the "not used" state, and free any allocated data structure. * 'Suspend': 'Command' is called with this value whenever the rule is inhibited. The rule must preserve its current "used" state, and enter the "not used" state. * 'Resume': 'Command' is called with this value whenever the rule is no more inhibited. The rule must restore its state from the copy saved by the previous 'Suspend' This procedure is required, since it must at least deal with the 'Rule_Used' flag (*note Process::). Note that it is guaranteed that 'Suspend'/'Resume' are properly paired, and that 'Suspend' is not called on an already suspended rule. Therefore, a simple variable can be used to save the current state. Ex: procedure Command (Action : Framework.Rules_Manager.Rule_Action) is use Framework.Rules_Manager; begin case Action is when Clear => Rule_Used := False; -- Free internal data structures if necessary when Suspend => Save_Used := Rule_Used; Rule_Used := False; when Resume => Rule_Used := Save_Used; end case; end Command; 3.3.4 Prepare ------------- 'Prepare' is a procedure that performs some initialisations that must be done after all controls refering to the rule have been parsed, and before processing the units. It is optional (i.e. a 'null' pointer can be passed for it to the 'Register' procedure, or simply not mentionned since 'null' is the default). A typical use of 'Prepare' is to balance the tree from a binary map to improve efficiency. 3.3.5 Process ------------- There is no special requirement on the implementation of the 'Process' procedure(s). The programmer is free to do whatever is necessary to the rule. It is possible to use ASIS query functions, or any other service deemed appropriate. It is also possible to have several 'Process' procedures (e.g. if the programmer wants to do some processing when going down the ASIS tree, and some other processing when going up). A 'Process' procedure should return immediately if no corresponding 'Add_Control' has ever been called. In most cases, this is conveniently done by having a 'Rule_Used' global boolean variable which is set to 'True' in 'Add_Control', and checked at the beginning of 'Process'. For efficiency reasons, avoid doing any call to the ASIS library before this check. This means that if you need objects initialized with such calls, they should be declared in a block after the test, rather than in the declarative part of the 'Process' procedure. After this test, the rule should immediately call 'Rules_Manager.Enter' (with the rule name as the parameter). In case of a problem, this allows the system to report which rule failed. A special case arises for rules that follow the call graph. Such rules may traverse elements outside the current unit, but should avoid analyzing units to which an 'inhibit all' applies (so-called banned units). The framework features an 'Is_Banned' function that tells if an element should not be traversed due to it being declared in a banned unit. See 'Rules.Global_References' for an example of this. 3.3.6 Finalize -------------- 'Finalize' is called at the end of a "Go" command, after all units have been processed. It is useful for rules that report on global usage of entities, and therefore can report findings only at the end. It is optionnal (i.e. a 'null' pointer can be passed for it to the 'Register' procedure, or simply not mentionned since 'null' is the default). Ex: procedure Finalize is begin -- Report findings end Finalize; 3.3.7 Package statements ------------------------ The package body statements part should include a call to 'Framework.Rules_Manager.Register' in order to register the rule and its associated 'Help', 'Add_Control', 'Command', and optionally 'Prepare' and 'Finalize', procedures. Note that the second parameter of 'Register' tells whether it is a semantic, textual, or semantic_textual rule. Ex: begin Framework.Rules_Manager.Register (Rule_Id, Rules_Manager.Semantic, Help => Help'Access, Add_Control => Add_Control'Access, Command => Command'Access, Prepare => Prepare'Access); end Rules.Pragmas; 3.4 Programming rules and tips ============================== 3.4.1 style ----------- We try to maintain a consistent style in AdaControl, therefore the code you write should match the style of the rest of the program. Have a look at other rules, and run 'src/verif.aru' on your code. In addition, please note the following: * The 'use' clause is allowed, but its scope should be restricted to the innermost declarative region where it is useful. Use a 'use' clause for ASIS units, and another one for other units. Sort units alphabetically in the clause. * The only output of a rule should be by calling 'Report'. Especially, no rule should use 'Wide_Text_IO' directly. * If your rule encounters a dynamic construct that prevents normal checking, call 'Framework.Reports.Uncheckable' to warn the user. * The framework should be sufficient for all your needs. If you have a special need that you think cannot be satisfied by the current framework, get in touch with us and we'll discuss it. 3.4.2 Things to care about -------------------------- Each time you want the name of something, remember that the name may be given in selected notation. In most cases, you should call 'Thick_Queries.Simple_Name' on the result of any query that returns a name to get rid of the possible selectors. Otherwise, you should inspect the returned expression to see if its 'Expression_Kind' is 'A_Selected_Component', and take the 'Selector' if it is. When designing a rule, consider the implications of renamings and generics. If you want to output the Element_Image of some element, beware that it will be preceded by spaces. Do not use 'Ada.Strings.Wide_Fixed.Trim' to eliminate them, since it wont remove tab characters. Use 'Utilities.trim_all', which will do the right thing. 3.4.3 Using ASIS efficiently. ----------------------------- Remember that ASIS queries can be costly. Declare local variables (or constants) rather than evaluating several times the same query. There are issues with some ASIS queries. The rule whose label is "Avoid_Query" in 'verif.aru' will remind you if you use one of these queries. Asis.Definitions.Subtype_Mark There might be confusion with 'Asis.Subtype_Mark'; moreover, you normally want to get rid of selected components (see above). Use 'Thick_Queries.Subtype_Simple_Name' instead. Asis.Definitions.Corresponding_Root_Type This query return a 'Nil_Element' if any type in the derivation chain is a ''Base' attribute (to be honnest, versions of ASIS before the latest 5.05 will loop indefinitely in this case). Use 'Thick_Queries.Corresponding_Root_Type_Name' instead, and consider what you want to do if there is a ''Base' in the derivation chain. Asis.Definitions.Corresponding_Parent_Subtype This query suffers from the same problem as 'Corresponding_Root_Type'. Don't use it, rather take the 'Subtype_Simple_name' of the 'Parent_Subtype_Indication', and do your own analysis, depending on whether the returned 'Expression_Kind' is 'An_Attribute_Reference' or not. 4 Plugging-in a new rule into the framework ******************************************* 4.1 Normal case =============== Adding a new rule to the tool requires only simple modifications to the package 'Framework.Plugs'. The package 'Framework.Plugs' contains several procedures that are called during the traversal of the code under the following circumstances: * 'Enter_Unit': Called when entering a compilation unit, before any other processing. * 'Exit_Unit': Called when leaving a compilation unit, after any other processing. * 'Enter_Scope': Called when entering a new scope (i.e. a construct that can contain declarations). * 'Exit_Scope': Called when leaving a scope. * 'Pre_Procedure': Called when entering a syntax node (this is like the usual 'Pre_Procedure' used in the instantiation of 'ASIS.Iterator.Traverse_Element', except that there is no 'State_Information' and no 'Control'). * 'Post_Procedure': Called when leaving a syntax node. * 'True_Identifier': Called when entering an 'An_Identifier', 'An_Operator_Symbol', or 'An_Enumeration_Literal' node that corresponds to a real identifier, i.e. not to a pragma name or other forms of irrelevant names. This avoids special cases in rules dealing with identifiers. * 'Text_Analysis': Called on every source line of the code. These procedures have the usual "big case" structure of an ASIS application (i.e. a first level case statement on 'Element_Kind', with each case alternative containing other case statements to further refine the kind of node that is being dealt with). The following modifications must be done to the body of this package: 1. Add a with clause naming the rule package: Ex: with Rules.Pragmas; 2. Add calls to the rule's 'Process' procedure(s) at the appropriate place(s) in the body of the provided procedures. For textual rules, 'Text_Analysis' is the only appropriate place. Ex: procedure Pre_Procedure (Element : in Asis.Element) is use Asis; use Asis.Elements; begin case Element_Kind (Element) is when A_Pragma => Rules.Pragmas.Process_Pragma (Element); ... end Pre_Procedure; Many alternatives of the big case statement cover a number of values. It may happen that a new rule requires calling its 'Process' procedure for some, but not all of these values. In this case, the case alternative must be split. This is not a problem, but do not forget to duplicate the statements from the original alternative before adding the new calls, to make sure that the split does not break existing rules. It is always possible to plug a 'Process' procedure in 'Pre_Procedure' or in 'Post_Procedure'. However, some "natural" places for plugging rules correspond to many branches of the big case statement. For example, there are many places where you enter a scope. That's why the package 'Framework.Plugs' includes other procedures that are called in "interesting" contexts. If appropriate, it is better practice to plug calls to 'Process' procedures here, rather than all over the place in various alternatives of the big case statement. 4.2 Specific rules ================== In some cases, you may want to keep your rules separate from the general purpose ones. This may happen if you have developped some very specific rules that take the structure of your project into account, and hence would not be of interest to anybody else. Or it may be that your local lawyer does not allow you to publish your rules as free software. This should not prevent you from using AdaControl. Just write the rules as usual, but instead of plugging them in 'Framework.Plugs', use the package 'Framework.Specific_Plugs' instead. This package has subprograms identical to those described above for plugging-in rules, and they are called in the same contexts. But it is guaranteed that no rule from the public release of AdaControl will ever be plugged-in into this package. This way, you can keep your rules separate from the public ones, and you can upgrade to a new version of AdaControl without needing to merge the modifications for your rules. If you have specific rules plugged into 'Framework.Specific_Plugs', change the constant 'Specific_Version' in the specification of the package to something that identifies the specific version (like your company's name for example). This way, the version number of AdaControl will show that it is a specific version. 4.3 User documentation ====================== Of course, you should update the user's guide with the information about your rules. This guide is written in Texinfo, see . Note however that you don't need to understand all the possibilities of Texinfo to update the manual; look at the description of other rules, the few commands you need will be quite straightforward to understand. 5 Testing and debugging a rule ****************************** 5.1 Testing =========== Once the rule is written, you will test it. Of course, you'll first write a small test case to make sure that it works as expected. But that's not enough. Our experience with existing rules has shown that getting the rule 90% right is quite easy, but the last 10% can be tricky. Ada offers constructs that you often didn't think about when writing the rule; for example, if you are expecting a name at some place, did you take care of selected names (we got trapped by this one several times)? Therefore, it is extremely important that you check your rule against as much code as you can, the minimum being the code of AdaControl itself. Note that if your rule encountered some uncheckable cases, you should add a child for your rule to the test 't_uncheckable', and also modify the 't_uncheckable.aru' file accordingly. Look at how it is done currently, and do the same. 5.2 Debugging aids ================== As mentionned above, it is often the case when writing a new rule, as well as with any kind of ASIS programming, that one comes across unexpected contexts. This is due to the rich features of Ada, but it is sometimes difficult to understand what is happenning. The framework provides some facilities that help in debugging. Don't hesitate to use the 'Trace' and 'Assert' utilities. *Note The package Utilities::. Note that the 'Trace' procedures may be given an element (or an element list) whose basic characteritics are printed. If the 'With_Source' parameter is 'True', the source correponding to the element is also printed. In the case where AdaControls enters an endless loop, the first thing to do is to determine the place where the loop is happening. To ease this, AdaControl may be compiled in "interruptible" mode. In normal mode, the package 'Framework.Interrupt' is a renaming of 'Framework.Interrupt_Std', a dummy package that does nothing. Edit 'Framework.Interrupt' to make it a renaming of 'Framework.Interrupt_Dbg' (instructions provided in the package) and recompile. Now, when you hit Ctrl-C while AdaControl is running with the "-d" option, execution of the current "go" command is interrupted with a message telling which rule is active, and on which compilation unit. If the "-x" option is also given, the whole execution is stopped. Of course, when you are done, reestablish the normal package by doing the inverse manipulation. The reason we didn't put the debug version in the regular version is that it drags in the whole tasking run-time, with a measurable impact on efficiency (we measured 18% extra time for running AdaControl on the ACATS). In addition, a small stand-alone utility called 'ptree' is provided. It prints the logical nesting of ASIS elements for a unit. The syntax of Ptree is: ptree [-sS] [-p ] [:] -- ::= | []-[] | : If the "-s" option is given, 'ptree' processes the specification of the unit, otherwise it processes the body. If the "-S" option is given, the span of each element is also printed. The "-p" option has the same meaning as in AdaControl itself. ASIS options can be passed, like for AdaControl, after a "--" (but -FS is the default). The is given either as an Ada unit, or as a file name, provided the extension is ".ads" or ".adb" (as in AdaControl). If a span is mentionned behind the unit name, only the constructs that cover the indicated span are output. The syntax of the span is the same used by pfni. This is useful if you are interested in just one particular structure in a big unit. If you come across a situation where you don't understand the logical nesting of elements, try to reduce it to a very simple example, then run 'ptree' on it. It can be quite instructive! Of course, a more elaborated, but less convenient solution is to use Asistant. Please refer to your ASIS documentation to learn how to use Asistant. Finally, if you come to suspect that you get a strange result from an ASIS provided operation, check whether there is an equivalent operation in the package 'A4G_Bugs', and if yes, use it instead. *Note The package A4G_Bugs::. 5.3 Integrating the test in the test suite ========================================== When your rule has been carefully tested and is ready for integration, run the rule file 'src/verif.aru' on every unit that you have written or changed. This will control that you match the programming rules for AdaControl. There can be some "found" messages (try to minimize them if possible), but there should be no "Error" message. Then, the last thing you have to do is to write a test for non-regression verification purpose. Don't forget to include examples of the tricky cases in the test. Go to the 'test' directory. You'll notice that all test programs have a name of the form 't_name.adb' (or in some rare cases, 'ts_name.adb'). The 'name' is the rule name. You'll notice also that some units have a name like 'tfw_name.adb'; these are tests for the framework, you should normally ignore them. Name your test file according to this convention, normally using 't_', unless the test requires some weird parameters that prevent it from being run normally, in which case it should use 'ts_' ("s" stands for special). It is OK for your test to have child units (whose names will be dictated by the Gnat naming convention). If your test requires other units, name them like 'x_name' or 'x_name_complement'. Then, go to the 'test/conf' directory, and put your rule file under the name 't_name.aru' (with the same 'name' of course). Go back to the 'test' directory, and run 'test.sh'. All tests should report PASSED, except the 'tfw_help' and 'tfw_check' tests. Your test will not be reported, because its expected output is not yet in the directory 'test/ref'; test 'tfw_help' will report FAILED because this test prints all help messages, and that the help message for your rule has been added; test 'tfw_check' will report FAILED because there is now one extra message (from the extra rule file) saying "No error found". Check that the result of your test is OK (in the file 'test/res/t_name.txt'), and copy this file to the directory 'test/ref/'. Do the following command: diff test/ref/tfw_help.txt test/res/tfw_help.txt and check that the only difference is the addition of the help message from your rule. Do the following command: diff test/ref/tfw_check.txt test/res/tfw_check.txt and check that the only difference is the addition of one "No error found" message. Then copy 'test/res/tfw_help.txt' and 'test/res/tfw_check.txt' to the directory 'test/ref/'. Run 'test.sh' again: it should print PASSED for all tests, including yours. Pay special attention to the last test, called 'tfw_stress'. This test runs all rules against all test units. If it fails, the file 'res/tfw_stress.txt' contains the whole listing of the run (with '-dv' options), so you'll find all the context of the problem. In case of problems, note that options can be passed to 'test.sh'; check the comments at the top of the file for details. When everything is OK, all you have to do is send your modifications (including the tests) to rosen@adalog.fr, for inclusion in the next release of AdaControl! adactl-1.17r3/doc/adacontrol_ug.txt0000644000175000017510000146022312621403304016431 0ustar rosenadalogAdaControl User Guide ********************* Last edited: November 13, 2015 This is the AdaControl User Guide. It describes how to install and use AdaControl. Please refer to the AdaControl Programmer Manual to learn how to add new kinds of rules to AdaControl. AdaControl is Copyright (C) 2005-2015 Eurocontrol/Adalog, except for some specific modules that are (C) 2006 Belgocontrol/Adalog, (C) 2006 CSEE/Adalog, (C) 2006 SAGEM/Adalog, or (C) 2015 Alstom/Adalog. AdaControl is free software; you can redistribute it and/or modify it under terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This unit is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License distributed with this program; see file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception, if other files instantiate generics from this program, or if you link units from this program with other files to produce an executable, this does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Public License. This document is Copyright (C) 2005-2015 Eurocontrol/Adalog. This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. 1 Introduction ************** AdaControl is an Ada rules controller. It is used to control that Ada software meets the requirements of a number of parameterizable rules. It is not intended to supplement checks made by the compiler, but rather to search for particular violations of good-practice rules, or to check that some rules are obeyed project-wide. AdaControl can also be handy to make statistics about certain usages of language features, or simply to search for the occurrences of particular constructs; its scope is therefore not limited to enforcing programming rules, although it is of course one of its main goals. AdaControl is a commercial product of Adalog (http://www.adalog.fr/adalog2.htm) with professional grade support available. Getting support is highly recommended for industrial projects. Adacontrol can also be customized or extended to match your special needs, please refer to *note Support:: or contact Adalog at . 1.1 Features ============ AdaControl analyzes a set of Ada units, according to parameterizable controls. Controls can be given from the command line, from a file, or interactively. There is a wide range of controls available. Some are quite simple (although very useful): * Control physical layout of the program (Maximum line length, no use of tabulations...) * Control occurences of special strings in comments (like TBD for "To Be Defined"), with full wildcarding. * Use of features (goto statement, tasking, pointers, variables in package specifications...) * Use of any declared entity, with full overloading resolution Other rules are quite sophisticated: * Control series of "if"..."elsif" that could be replaced by "case" statements * Verify usage of declarations (variables that should be constant, variables read but not written...) * Control declarations that could be moved to a more reduced, internal scope * Limit the call depth of a program (and diagnose recursive subprograms) * Enforce a pattern that guarantees that exceptions are not handled silently * Enforce a pattern for paired calls (like semaphore's "P" and "V") that guarantees that the closing call is always executed, even in presence of exceptions. * Check that there is no aliasing between out parameters * Ensure that no protected operation calls a potentially blocking operation and much, much more... See *note Rules reference:: for the complete reference for all possible controls. AdaControl is very simple to use. It takes, as parameters, a list of units to process and a list of commands that define the controls to apply. The complete syntax of the commands is described in chapter *note Command language reference::. AdaControl produces messages to the standard output, unless redirected. Several levels of messages are defined (i.e. error or found), depending on the kind of the control (i.e. check or search). Rules can be locally disabled for a part of the source code, and various options can be passed to the program. Ex: Given the following package: package Pack is pragma Pure (Pack); ... end Pack; The following command: adactl -l "search pragmas (pure)" pack produces the following result (displayed to standard output): pack.ads:2:4: Found: PRAGMAS: use of pragma Pure AdaControl integrates nicely in environments such as GPS (*note Running AdaControl from GPS::), AdaGide (*note Running AdaControl from AdaGide::), or emacs (*note Control kinds and report messages::). In those environments, you can run AdaControl from menus or by just clicking on a button! 1.2 Support =========== 1.2.1 Commercial support ------------------------ Adalog provides commercial support for AdaControl. Support includes the following benefits: * Help with installation procedures. * Explanations regarding the use of the tool, and help for translating coding standards into AdaControl rules. * Dedicated account into our BT system for priority handling of problem reports. * Correction of problems encountered in the use of AdaControl. Pre-releases versions of AdaControl are provided for each corrected problem. * Access to beta-versions before they are released * Keeping in sync customer's own custom rules with the latest version of AdaControl. * Reduced rate for on-demand development of custom rules. * Priority consideration of enhancement requests. Satisfying enhancement requests is not part of the support contract; however, Adalog is constantly improving AdaControl, and suggestions originating from supported customers are given a high priority in our todo list. Adalog cannot correct problems whose origin is due to compiler bugs or defects in the implementation of ASIS (contact your compiler provider for support on these problems). However, Adalog will do its best effort to find workarounds for such problems. In addition, Adalog can provide various services: * Custom improvements to AdaControl, including application-specific rules; * consulting services for defining coding standards; * consulting services in all areas related to Ada, real-time, compilation, etc. See Adalog's site (http://www.adalog.fr/adalog2.htm) for details. For pricing information about support contract and other services, please contact . 1.2.2 Other support ------------------- There is a Wiki for questions about AdaControl at . This is the place to ask for information, make suggestions, or get help from the community. For problem reports, please create a ticket into our BT system at . 1.2.3 Your support to us, too! ------------------------------ If you enjoy AdaControl, there are several things you can do to help us continue and improve this nice project. * Rate it, or even better post a review, on the SourceForge review page (http://sourceforge.net/projects/adacontrol/reviews/) * Click "I use it" from AdaControl's home page (http://www.adalog.fr/adacontrol2.htm). * Rate it on AdaControl's Ohloh page (http://www.ohloh.net/p/11353?ref=sample) * Get a support contract, or encourage your company, your friends, or anybody else to get a support contract! * Provide good ideas, new rules, suggestions for improvements... And remember: developing AdaControl is an expensive effort (according to Ohlo's COCOMO model, it is worth 15 man.year of development). We need support from our users to keep it running! 1.3 History =========== The development of AdaControl was initially funded by Eurocontrol (), which needed a tool to help in verifying the million+ lines of code that does Air Traffic Flow Management over Europe. Because it was felt that such a tool would benefit the community at-large, and that further improvements made by the community would benefit Eurocontrol, it was decided to release AdaControl as free software. Later, Eurocontrol, Belgocontrol, Ansaldo (formerly CSEE-Transport), and SAGEM-DS sponsored the development of more rules. The requirements for AdaControl were written by Philippe Waroquiers (Eurocontrol-Brussels), who also conducted extensive testing of AdaControl over the Eurocontrol software. The software was developped by Arnaud Lecanu and Jean-Pierre Rosen (Adalog). Rules, improvements, etc. were contributed by Pierre-Louis Escouflaire (Adalog), Alain Fontaine (ABF consulting), Richard Toy (Eurocontrol-Maastricht), and Isidro Ilasa Veloso (GMV). AdaGide support and improvement of icons were contributed by Gautier de Montmollin. Emmanuel Masker (Alstom) and Yannick Duchene contributed to GPS integration. See file 'HISTORY' for a description of the various versions of AdaControl, including enhancements of the current version over the previous ones. Users of a previous version are warned that the rules are not 100% upward-compatible: this is necessary to make the rules more consistent and easier to use. However, the incompatibilities are straightforward to fix and should affect only a very limited number of files. See *note Non upward-compatible changes:: for details. 1.4 References ============== 1. "On the benefits for industrials of sponsoring free software development", Ada User Journal, Volume 26, number 4, december 2005 2. "A Comparison of Industrial Coding Rules", Ada User Journal, Volume 29, number 4, december 2008 3. "A Methodology for Avoiding Known Compiler Problems Using Static Analysis", proceedings of the ACM SIGAda Annual International Conference (SIGAda 2010) 2 Installation ************** Like any ASIS application, AdaControl can be run only if the compiler available on the system has exactly the same version as the one used to compile AdaControl itself. The executable distribution of AdaControl will work only with GNAT version GPL 2015, as distributed by AdaCore. If you are using any other version, please use the source distribution of AdaControl and compile it as indicated below. Another reason for using the source distribution of AdaControl is that the user may not be interested in all provided rules. It is very easy to remove some rules from AdaControl to increase its speed. *Note Customizing AdaControl::. 2.1 Building AdaControl from source =================================== This section is only for the source distribution of AdaControl. If you downloaded an executable distribution (and are using the latest version of GNAT GPL), you may skip to the next section. 2.1.1 Getting the correct version of the sources for your Gnat version ---------------------------------------------------------------------- ASIS is continuously evolving to support Ada-2005/2012 features, and so is AdaControl. As a consequence, the full set of features of AdaControl is supported only with recent versions of Gnat, namely with GnatPRO 7.2.0 and GnatGPL-2013 (and higher). We refer to these versions as the "new Gnat", and we encourage all users to use the latest versions. Some user may however need to use an older version of Gnat. We provide also a version of AdaControl that is compatible with versions GnatPRO 7.0.x and GnatGPL-2011 and older (before some incompatible -but necessary- changes in ASIS happened). We refer to these versions as the "old Gnat". The release whose distribution files start with "adactl" is for the new Gnat, and the one whose distribution files start with "adactl-old" is for the old-gnat. Both versions provide the same features, except that controls related to Ada-2012 (or that depend on new features of ASIS) are not available in the old-gnat version. Moreover, the old-gnat version is now frozen, and will not receive any new features or improvements in the future, unless requested by a supported customer (such requests will be honoured as part of the support contract). See *note Support:: for information on becoming a supported user. Note that intermediate releases of Gnat (GnatPRO-7.1.x, GnatGPL-2012) are not fully compatible with either of these distribution. Depending on exact version, problems may range from compilation errors to incorrect results in some rare (Ada 2012) cases. Compatible sources can be obtained from the Git repository of AdaControl on SourceForge (). We will be happy to help our supported customers who must use one of these versions. 2.1.2 Prerequisites ------------------- The following software must be installed in order to compile AdaControl from source: * A GNAT compiler, any version (but please consider *note Getting the correct version of the sources for your Gnat version:: above). Note that the compiler must also be available on the machine in order to run AdaControl (all ASIS application need the compiler). * ASIS for GNAT Make sure to have the same version of GNAT and ASIS. The version used for running AdaControl must be the same as the one used to compile AdaControl itself. 2.1.3 Build with installer (Windows) ------------------------------------ Run the installer ('adactl_src-setup.exe'). This will automatically build and install AdaControl, no other installation is necessary. 2.1.4 Build with project file ----------------------------- Simply go to the 'src' directory and type: gnatmake -Pbuild.gpr You're done! Caveat (old gnat only): Due to a bug in some versions, if you are using GNATPro 6.1.2 and above, you must set the variable GNAT_FIX to 1; i.e. invoke the command as: gnatmake -Pbuild.gpr -XGNAT_FIX=1 2.1.5 Build with Makefile ------------------------- The previous method may fail if Asis is not installed in an usual place. As an alternative method, it is possible to build AdaControl with a regular Makefile. The file 'Makefile' (in directory 'src') should be modified to match the commands and paths of the target system. The following variables are to be set: * ASIS_TOP * ASIS_INCLUDE * ASIS_OBJ * ASIS_LIB * RM * EXT How to set these variables properly is documented in 'Makefile'. See also the compilation options in this file; a change is needed if you are using GNATPro 6.1.2 and above. Then, run the make command: $ cd src $ make build It is also possible to delete object files and do other actions with this "Makefile", run the following command to get more information: $ make help NOTE: Building AdaControl needs the "make" command provide with GNAT; it works both with WIN32 shell and UNIX shell. 2.1.6 Build with a compiler other than GNAT ------------------------------------------- It should be possible to compile AdaControl with other compilers than GNAT, although we didn't have an opportunity to try it. If you have another compiler that supports ASIS, note that it may require some easy changes in the package 'Implementation_Options' to give proper parameters to the 'Associate' procedure of ASIS. Rules that need string pattern matchings need the package 'Gnat.Regpat'. If you compile AdaControl with another compiler, you can either port 'Gnat.Regpat' to your system, or use a (limited) portable implementation of a simple pattern matching (package 'String_Matching_Portable'). Edit the file 'string_matching.ads' and change it as indicated in the comments. No other change should be necessary. Alternatively, if you are using another compiler, you can try and compile your program with GNAT just to be able to run AdaControl. However, compilers often differ in their support of representation clauses, which can cause your program to be rejected by GNAT. In that case, we provide a sed script to comment-out all representation clauses; this can be sufficient to allow you to use AdaControl. *Note unrepr.sed::. 2.1.7 Testing AdaControl ------------------------ Testing AdaControl needs a UNIX shell, so it works only with UNIX systems. However, it is possible to run the tests on a WIN32 system by using an UNIX-like shell for WIN32, such as those provided by CYGWIN or MSYS. To run the tests, enter the following commands: $ cd test $ ./run.sh All tests must report PASSED. If they don't, it may be due to one of the following issues: * You are using an old version of GNAT. AdaControl runs without any known problem (and it has been checked against the whole ACATS) only with the latest GNATPro and GNATGPL versions; earlier versions are known to have bugs and unimplemented features that will not allow AdaControl to run correctly in some cases. We strongly recommend to always use the most recent version of GNAT. * You run an old-gnat version of AdaControl with GNATPro (6.1.2 and above) and you forgot to specify the "-XGNAT_FIX=1" option. *Note Build with project file::. * It may happen that the test 'tfw_help' reports "FAILED" because it includes a check on the version of AdaControl, and the version string refers to Gnat-GPL2015. The only difference (you can see it by typing "d" when prompted for checking the differences) should be the name of the compiler. 2.1.8 Customizing AdaControl ---------------------------- If there are some rules that you are not interested in, it is very easy to remove them from AdaControl: 1. In the 'src' directory, edit the file 'framework-plugs.adb'. There is a 'with' clause for each rule (children of package 'Rules'). Comment out the ones you don't want. 2. Recompile 'framework-plugs.adb'. There will be error messages about unknown procedure calls. Comment out the corresponding lines. 3. Compile AdaControl normally. That's all! It is also possible to add new rules to AdaControl. If your favorite rules are not currently supported, you have several options: 1. If you have some funding available, please contact info@adalog.fr. We'll be happy to make an offer to customize AdaControl to your needs. 2. If you don't have funding, but have some knowledge of ASIS programming, you can add the rule yourself. We have made every effort to make this as simple as possible. Please refer to the AdaControl programmer's manual for details. If you do so, please send your rules to rosen@adalog.fr, and we'll be happy to integrate them in the general release of AdaControl to make them available to everybody. 3. If you have good ideas, but don't feel like implementing them yourself (nor financing them), please send a note to rosen@adalog.fr. We will eventually incorporate all good suggestions, but we can't of course commit to any dead-line in that case. 2.2 Installing AdaControl ========================= All you need to run AdaControl is the executable named 'adactl' under Linux or 'adactl.exe' under Windows. In addition, 'pfni' (or 'pfni.exe' under Windows) is a convenient utility, required by the GPS support. *Note pfni::. If you downloaded the Windows installer executable version of AdaControl, simply run 'adactl_exe-setup.exe'. This will install all the files in the recommended locations (as has been done with the Windows installer source version), including GPS support if you have GPS installed and/or AdaGide support if you have AdaGide installed. If you built AdaControl from source without an installer, the executables are in the 'src' directory of the distribution. If you downloaded an executable distribution, they are in the root directory of the distribution. Copy the executables to any convenient directory on your path; a good place, for example, is in the 'bin' directory of your GNAT installation. 2.3 Installing support for GPS ============================== Integration of AdaControl into GPS with all functionalities requires GPS version 4.2 or above (delivered since GNAT/GPL2008). To add AdaControl support to GPS, copy the file 'GPS/adacontrol.xml' into the '/share/gprconfig' directory; copy all other files from the 'GPS' directory into the '/share/gps/plug-ins' directory. Copy also HTML files from the 'doc' directory into the '/share/doc/gps/html' to access AdaControl's guides from the "Help" menu of GPS. 2.4 Installing support for AdaGide ================================== To add AdaControl support to AdaGide, copy the file 'AdaControl.tdf' from the 'AdaGide' directory into AdaGide's root directory. Note that AdaControl support requires AdaGide version 7.42 or above. 3 Program Usage *************** AdaControl is a command-line program, i.e. it is normally called directly from the system shell. Options are introduced by a "-" followed by a letter and can be grouped as usual. Some options take the following word on the command line as a value; such options must appear last in a group of options. Parameters are words on the command line that stand by themselves. Options and parameters can be given in any order. The syntax for invoking AdaControl in regular mode is: adactl [-deEirsTuvwx] [-p ] [-f ] [-l ] [-o ] [-t ] [-F ] [-S ] [-m ] [-M ] {[+|-]|[@]} [-- ] AdaControl can process Ada-2012 as well as Ada-95 programs, even if there are currently few Ada-2012 related controls - but we hope to improve that situation in the near future. If you are using Ada-2005 (or Ada-2012) features, make sure that GNAT is set up for Ada-2005/2012 (this is the default for GNAT-GPL). Due to technical reasons, the -gnat05 option cannot be passed to the compiler in "compile on the fly" mode, but you can do any of the following: * have a "gnat.adc" file in the current directory that contains a 'pragma Ada_05;' (or 'pragma Ada_12;') * put a 'pragma Ada_05' (or 'pragma Ada_12;') on top of every compilation unit that uses Ada-2005/2012 features; * generate the tree files manually (*note Generating tree files manually::) with the "-gnat05" (or "-gnat12)") option. Note that this allows you to pass any other GNAT option as well. Note that if your program is pure Ada-95 and you are using a version of GNAT where Ada-2005 is the default (especially GNAT-GPL), and in the rare cases where your program would not compile in Ada-2005 mode (notably if you have a function that returns a task type), you can force Ada-95 the same way by using 'pragma Ada_95' instead. 3.1 Command line parameters and options ======================================= 3.1.1 Input units ----------------- Units to be processed are given as parameters on the command line. Note that they are Ada _compilation unit_ names, not _file names_: case is not significant, and there should be no extension! Child units are allowed following normal Ada naming rules: 'Parent.Child', but be aware that specifying a child unit will automatically include its parent unit in the analysis. Subunits are processed during the analysis of the including unit; there is therefore no need to specify subunits explicitely. If you do specify a subunit explicitly, it will result in the whole enclosing unit being analyzed. However, as a convenience to the user, units can be specified as file names, provided they follow the default GNAT naming convention. More precisely, if a parameter ends in ".ads" or ".adb", the unit name is extracted from it (and all "-" in the name are substituted with "."). File names can include a path; in this case, the path is automatically added to the list of directories searched ("-I" ASIS option). The file notation is convenient to process all units in a directory, as in the following example: adactl -f my_rules.aru *.adb In the unlikely case where you have a child unit called 'Ads' or 'Adb', use the "-u" option to force interpretation of all parameters as unit names. By default, both the specification and body of the unit are processed; however, it is possible to specify processing of the specification only by providing the "-s" option. If only file names are given, the "-s" option is assumed if all files are specifications (".ads" files). It is not possible to specify processing of bodies only, since rules dealing with visibility would not work. The "-r" option tells AdaControl to process (recursively) all user units that the specified units depend on (including parent units if the unit is a child unit or a subunit). Predefined Ada units and units belonging to the compiler's run-time library are never processed. Ex: adactl -r -f my_rules.aru my_main will process 'my_main' and all units that 'my_main' depends on. If 'my_main' is the main procedure, this means that the whole program will be processed. It is possible to specify more than one unit (not file) to process in a parameter by separating the names with "+". Conversely, it is possible to specify units that are not to be processed, separated by "-". When a unit is subtracted from the unit list, it is never processed even if it is included via the recursive option, and all its child and separate units are also excluded. This is convenient to avoid processing reusable components, that are not part of a project. For example, if you want to run AdaControl on itself, you should use the following command: adactl -f my_rules_file.aru -r adactl-asis-a4g This applies the rules from the file 'my_rules_files.aru' to AdaControl itself, but not to units that are part of ASIS (units 'Asis', 'A4G', and their children) that would be found by the "-r" (recursive) option otherwise. Alternatively, it is possible to provide units indirectly with a parameter consisting of an "@" followed by the name of a file. This file must contain a list of unit names (not files), one on each line. Only the first "word" of the line is considered, i.e. everything after the first blank is ignored. This can be useful to annotate unit names. All units whose names are given in the file will be processed. If a name in the file starts with "@", it will also be treated as an indirect file (i.e. the same process will be invoked recursively). If a line in the file starts with "#" or "--", it is ignored. This can be useful to temporarily disable the processing of some files or to add comments. Ex: adactl -f my_rules.aru @unit_file.txt 3.1.2 Commands -------------- Commands specify which processing AdaControl should apply to units. See *note Command language reference:: for a detailed description of all commands. Commands can be given directly on the command line with the "-l" option. A commands list must be quoted with """. Ex: adactl pack.ads proc.adb -l "check instantiations (My_Generic);" It is possible to pass several commands separated by ";", but as a convenience to the user, the last ";" may be omitted. Commands can also be read from a file, whose name is given after the "-f" option (the "'.aru'" extension is taken by default). As a special case, if the file name is "-", commands are read from the standard input. This is intended to allow AdaControl to be pipelined behind something that generates commands; if you want to type commands directly to AdaControl, the interactive mode is more appropriate. *Note Interactive mode::. Ex: adactl -f my_rules.aru proc.adb Note that the "-l" and "-f" options are not exclusive: if both are specified, the commands to be performed include those in the file (first) and then those given on the command line. 3.1.3 Output file ----------------- Messages produced by controls are output to the output file; by default, it is the standard output, but it can be changed by specifying the "-o" option. Ex: adactl -f my_rules.aru -o my_output.txt proc.adb If the output file exists, new messages are appended to it. This allows running AdaControl under several directories that make up the project, and gathering the results in a single file. However, if the "-w" option is given, AdaControl overwrites the output file if it exists. All other messages, including syntax error messages, units processed (in verbose mode), and possible internal error mesages from AdaControl itself are output to the standard error file. 3.1.4 Output format ------------------- The "-F" option selects the output format. It must be followed by "Gnat", "Gnat_Short", "CSV", "CSV_Short", "Source", "Source_Short", or "None" (case insensitive). By default, the output is in "Gnat" format. See *note Control kinds and report messages:: for details. The "-S" option selects which statistics are output after each run. It must be followed by a value in the range 0..3. See *note Control kinds and report messages:: for details on the various statistics levels. The "-T" option prints a summary of timing at the end of each run. This indicates how long (in real-time seconds) was spent in processing each rule. Ex: adactl -F CSV -S 2 -f my_rules.aru -o my_output.csv proc.adb 3.1.5 Output limits ------------------- The "-m" and "-M" options are used to limit the output of AdaControl. These options are followed by an integer value that specifies the maximum number of error messages ("-m") or warning and error messages ("-M"). If the value is omitted, a previous limitation (comming for example from a command file) is cancelled. If the indicated number of messages is exceeded during a run, AdaControl stops immediately. 3.1.6 Project files ------------------- An emacs project file (the file with a ".adp" extension used by the Ada mode of Emacs) can be specified with the " -p" option. AdaControl will automatically consider all the directories mentioned in "src_dir" lines from the project file. Ex: adactl -f my_rules.aru -p proj.adp proc.adb Note that AdaControl does not accept ".gpr" project files, because ASIS does not currently accept the "-P" option like other GNAT commands do. However, when run from GPS, the interface will automatically use the source directories from the current (root) project (unless you have explicitely set a ".adp" file in the switches *note AdaControl switches::). If you have a project that uses ".gpr" project files and you want to run AdaControl from the command line (not from GPS), you can generate a ".adp" project file from a ".gpr" project file from within GPS, by using the "Tools/AdaControl/Generate .adp project" menu. *Note Running AdaControl from GPS::. Alternatively, it is also possible to use GPS project files by generating the tree files manually. *note Generating tree files manually:: for details. 3.1.7 Local disabling control ----------------------------- The "-i" option tells AdaControl to ignore disabling markers in Ada source code (*note Disabling controls::); i.e. all controls will be performed, regardless of the presence of disabling markers. This is equivalent to the command "'set ignore ON;'". Note that if you you have many messages, setting this option can speed-up AdaControl considerably. It is therefore advisable to always set this option when you know that there is no disabling marker in your source code. The "-j" option tells AdaControl to invert the meaning of disabling markers, i.e. only messages marked as disabled will be printed. This is useful to check which messages have been disabled. This is equivalent to the command "'set ignore INVERTED;'". 3.1.8 Verbose and debug mode ---------------------------- In the default mode, AdaControl displays only messages from triggered controls. It is possible to get more information with the verbose option ("-v"). In this mode, AdaControl displays a a progress indicator and unit names as they are processed, and its global execution time when it finishes. Note that the progress indicator includes an indication of the run number if there are more than one "go" command. The "-d" option enables debug mode. This mode provides more information in case of an internal program error, and is of little interest for the casual user. Note that if you hit Ctrl-C in debug mode, AdaControl aborts with a message telling the currently active rule and module. This can be useful if you suspect AdaControl to be stuck in an infinite loop. In debug mode, AdaControl may also, in rare occasions (and only with some versions of GNAT), display ASIS "bug boxes"; this does not mean that something went wrong with the program, but simply that an ASIS failure was properly recovered by AdaControl. Output of the messages printed by the "-d" option can be directed to a "trace" file (instead of being printed to the standard error file). This is done by the "-t" option, which must be followed by the file name. If the trace file exists, new messages are appended to it. 3.1.9 Treatment of warnings --------------------------- The "-e" option tells AdaControl to treat warnings as errors, i.e. to report a return code of 1 even if only "search" controls were triggered. *Note Return codes::. It does not change the messages however. Conversely, the "-E" option tells AdaControl to not report warnings at all, i.e. only errors are reported. However, if you ask for statistics, the number of warning messages is still counted. *Note Control kinds and report messages::. 3.1.10 Exit on error -------------------- If an internal error is encountered during the processing of a unit, AdaControl will continue to process other units. However, if the "-x" option is given, AdaControl will stop on the first error encountered. This option is mainly useful if you want to debug AdaControl itself (or your own rules). *Note In case of trouble::. Ex: adactl -x -f my_rules.aru proc.adb 3.1.11 ASIS options ------------------- Everything that appears on the command line after "--" will be treated as an ASIS option, as described in the ASIS user manual. Casual users don't need to care about ASIS options, except in one case: if you are running AdaControl from the command line (not from GPS), and if the units that you are processing reference other units whose source is not in the same directory, AdaControl needs to know how to access these units (as GNAT would). This can be done either by using an Emacs project file with the "-p" option (see *note Project files::), by putting the appropriate directories into the ADA_INCLUDE_PATH environment variable, or by passing "-I" options to ASIS. It is possible to pass one or several "-I" options to ASIS, to provide other directories where sources can be found. The syntax is the same as the "-I" option for GNAT. Other ASIS options, like the "-Cx" and/or "-Fx" options, can be specified. Most users can ignore this feature; however, specifying these options can improve the processing time of big projects. *Note Optimizing Adacontrol::. 3.2 Return codes ================ In order to ease the automation of controlling programs with shell scripts, AdaControl returns various error codes depending on how successful it was. Values returned are: * 0: At most "search" controls (i.e. warnings) were triggered (no control at all with "-e" option) * 1: At least one "check" control (i.e. error) was triggered (or at least one "search" or "check" control with "-e" option) * 2: AdaControl was not run due to a syntax error in the rules or in the specification of units. * 10: There was an internal failure of AdaControl. 3.3 Environment variable and default settings ============================================= If the environment variable "ADACTLINI" is set, its content is taken as a set of commands (separated by semi-colons) that are executed before any other command. Although any command can be specified, this is intended to allow changing default settings with "set" commands. *Note Set command::. For example, you can set ADACTLINI to "set format Gnat_Short" if you prefer having you messages in short format rather than the (default) long format. 3.4 Interactive mode ==================== The "-I" option tells AdaControl to operate interactively. In this mode, commands specified with "-l" or "-f" options are first processed, then AdaControl prompts for commands on the terminal. Note that the "quit" command (*note Quit command::) is used to terminate AdaControl. The syntax of commands run interactively is exactly the same as the one used for files; especially, each command must be terminated with a ";". Note that the prompt ("Command:") becomes ".......:" when AdaControl requires more input because a command is not completely given, and especially if you forget the final ";". As with files, it is possible to give several commands on a single line in interactive mode. If a command contains syntax errors, all "go" commands (*note Go command::) on the same line are temporarily disabled. Other commands that do not have errors are normally processed however. The interactive mode is useful when you want to do some analysis of your code, but don't know beforehand what you want to control. Since the ASIS context is open only once when the program is loaded, queries will be much faster than running AdaControl entirely with a new query given in a "-l" option each time. It is also useful to experiment with AdaControl, and to check interactively commands before putting them into a file. 3.5 Other execution modes ========================= In addition to normal usage, AdaControl features special options to ease its use; no Ada unit is analyzed when using these options. 3.5.1 Getting help ------------------ The "-h" option provides help about Adacontrol usage. If the "-h" option is given, no other option is analyzed and no further processing happens. Syntax: adactl -h [ | | variables [""] ...] ::= all | commands | license | list | options | rules | version The "-h" option without parameter displays a help message about usage of the AdaControl program, the various options, and the rule names. Otherwise, the "-h" must be followed by one or several keywords or rule names (case irrelevant); its effect is: * : if is exactly the name of rule, display the help message for the indicated rule. Otherwise, is interpreted as a pattern, and help messages for all rules that match the pattern is displayed. Patterns are given using the full Regexp syntax. *note Syntax of regular expressions:: for details. * "variables" lists the values of all variables whose name matches , or all variables if there is no . Patterns are given using the full Regexp syntax. *note Syntax of regular expressions:: for details. * "all": display the help message for all rules. * "commands": display a summary of all commands * "license": display the license information * "list": display the names of all rules (note that "rules" also displays the list of rules, in a prettier format; the "list" option is mainly useful for the integration of AdaControl into GPS). * "options": display help about the command-line options * "rules": display the names of all rules. * "version": display AdaControl and ASIS implementation version numbers. Ex: adactl -h pragmas Unnecessary_Use_Clause adactl -h all adactl -h version license adactl -h stat Note in the last example that "stat" is not the name of a rule; it is therefore interpreted as a pattern, and help will be displayed for all rules that include the string "stat" in their name. This can be very convenient to retrieve the name of a rule if you don't remember exactly how it is spelled. 3.5.2 Checking commands syntax ------------------------------ The "-C" option is used to check syntax of commands without executing any control. Syntax: adactl -C [-dv] [-f ] [-l ] In this mode, AdaControl simply checks the syntax of the commands provided with the "-l" option, or of the commands provided in the file named by the "-f" option (at least one of these options must be provided). No other processing will happen. AdaControl will exit with a return code of 0 if the syntax is correct, and 2 if any errors are found. A confirming message that no errors were found is output if the "-v" option is given. This option is especially useful when you have modified a rules file, before trying it on many units. The way AdaControl works, it must open the ASIS context (a lengthy operation) before analyzing the rules. This option can therefore save a lot of time if the rules file contains errors. 3.5.3 Generating a units list ----------------------------- The "-D" options produces a list of units that can be reused as an indirect file in later runs. Syntax: adactl -D [-rsvw] [-o ] [-p ] {[+|-]|[@]} [-- ] In this mode, AdaControl outputs the list of units that would be processed. It is especially useful when used with the "-r" option and given the main unit name, since it will then generate the whole list of dependent units (hence the name "D"). This list can be directed to a file with the "-o" option (if the file exists, it won't be overwritten unless the "-w" option is specified). This file can then be used in an indirect list of units. *Note Input units::. Note that it is more efficient to create the list of units once and then use the indirect file than to specify all applicable units or use the "-r" option each time AdaControl is run. 3.6 Running AdaControl from GPS =============================== If you want to use AdaControl from GPS, make sure you have copied the necessary files into the required places. *Note Installing AdaControl::. AdaControl integrates nicely into GPS, making it even easier to use. It can be launched from menu commands, and parameters can be set like any other GPS project parameters. When run from within GPS, AdaControl will automatically retrieve all needed directories from the current GPS project. After running AdaControl, the "locations" panel will open, and you can retrieve the locations of errors from there, just like with a regular compilation. Errors will be marked in red in the source, warning will be marked orange, and you will have corresponding marks showing the places of errors and warnings in the speedbar. Note that AdaControl errors appear under the "AdaControl" category, but if there were compilation errors, they will appear under the "Compilation" category. Final counts from "count" control kinds will appear under the "Counts summary" category, and statistics under the "Statistics" category. 3.6.1 The AdaControl menu and buttons ------------------------------------- GPS now features an "AdaControl" menu, with several submenus: * "Control Current File (rules file)" runs AdaControl on the currently edited file, with rules taken from the current rules file; this menu is greyed-out if no rules file is defined, if no file window is currently active, or if the associated language is not "Ada". The name of the rules file can be set from the "Library" tab from the "Project/Edit Project Properties" menu. * "Control Root Project (rules file)" runs AdaControl on all units that are part of the root project, with rules taken from the current rules file; this menu is greyed-out if no rules file is defined. The name of the rules file can be set from the "Library" tab from the "Project/Edit Project Properties" menu. * "Control Units from List (rules file)" runs AdaControls on units given in a indirect file, with rules taken from the current rules file. This menu is greyed-out if no rules file is defined or if no indirect file is defined. The name of the rules file and of the indirect file can be set from the "Library" tab from the "Project/Edit Project Properties" menu. * "Control Current File (interactive)" runs AdaControl on the currently edited file, with a rule asked interactively from a pop-up; this menu is greyed-out if no file window is currently active, or if the associated language is not "Ada". * "Control Root Project (interactive)" runs AdaControl on all units that are part of the root project, with a rule asked interactively from a pop-up. * "Control Units from List (interactive)" runs AdaControls on units given in a indirect file, with a rule asked interactively from a pop-up. This menu is greyed-out if no indirect file is defined. The name of the indirect file can be set from the "Library" tab from the "Project/Edit Project Properties" menu. * "Check Rules File" checks the syntax of the current rules file. This menu is deactivated if the current window does not contain an AdaControl rules file. * "Open Rules File" opens the rules file. This menu is deactivated if there is no current rules file defined. * "Open Units File" opens the units file. This menu is deactivated if there is no current units file defined. * "Create units file" creates a text file containing all units (not files) names from the current root project. This file is appropriate as an indirect file for the "... from list" commands. * "Create .adp project" creates an Emacs-style project file from the current GPS project, which can be used with the "-p" option if you want to run AdaControl from the command line. This file has the same name as the current GPS project, with a ".adp" extension. *Note Project files::. * "Delete Tree Files" removes existing tree files from the current directory. This is convenient when AdaControl complains that the tree files are not up-to-date. Note that you can set the preferences for automatic deletion of tree files after each run (see below). Note that the name of this menu is changed to "Delete Tree and .ali Files" if you have chosen to delete .ali files in the preferences (see below). * "Load results file" loads in the location window the result file obtained from a previous run of AdaControl. The file must have been produced with the "Gnat" or "Gnat_Short" format. *Note Control kinds and report messages::. There are also two buttons representing Lady Ada in a magnifier glass in the toolbar, one with a red question mark in the background. These buttons launch AdaControl, by default on the file currently being edited; however, you can change this behaviour from the preferences to control either files from a list, or all files from the project. The button without the question mark uses rules from the current rules file, while the one with the question mark asks for the control to apply interactively. Here are some tips about using the "interactive" menus (or the button with the question mark): * When you use the "interactive" menus several times, the previously entered command(s) is used as a default. * You can enter any command from AdaControl's language in the dialog; you can even enter several commands separated by ";". * Especially, if you want to run AdaControl with a rules file that is not the one defined by the switches, you can use one of the "interactive" commands, and give "source " as the command. 3.6.2 Contextual menu --------------------- AdaControl adds two entries to the contextual menus (right click) of Ada files. They call the 'pfni' utility on the current entity. *Note pfni::. The entry "Print full name" displays the full name of the entity in simple form, while the entry "Print full name (with overloading)" ) prints it with overloading information. If the name refers to an entity which is initialized (or to a parameter with a default value), the initial value is printed. If the entity is a discrete type, its range is printed. If the entity is an array type, the ranges of its indices are printed. This is convenient to find how to name entities in rule files. *Note Specifying an Ada entity name::. It is also convenient to find where an entity is declared, and which of several overloaded entities is being referred to. This is also convenient to find the actual value of a constant from anywhere in the program text, since the printed value is completely evaluated if it is a (static) expression. 3.6.3 AdaControl switches ------------------------- The tab "switches" from the "Project/Edit Project Properties" menu includes a page for AdaControl, which allows you to set various parameters. Since the GPS interface analyzes the output of AdaControl, you should not set options directly in the bottom window of this page (the one that displays the actual options passed to AdaControl). 3.6.3.1 Files ............. This section controls the definition of various files used by AdaControl. * "Rules file". This is the name of a file that contains the definition of the controls to be applied to your project. This file is required for all "control (rules file)" commands. * "Units file". This is the name of a file that contains the list of units to be controlled. This file is required for all "control from list" commands. * ".adp project file". This is the name of an emacs project file (.adp). If this name is not empty, AdaControl will use it instead of providing all libraries as "-I" options on the command line. This may be necessary if you have many libraries and the command line that launches AdaControl becomes too long. Note that this file can be created using the "AdaControl/Create .adp project" menu. 3.6.3.2 Processing .................. This section offers options that control how units are processed. * "Recursive mode". This sets the "-r" option. *Note Input units::. * "Ignore local deactivation". This sets the "-i" option. *Note Local disabling control::. * "Process specs only". This sets the "-s" option. *Note Input units::. * "Compilation unit mode". This sets the "-u" option. *Note Input units::. 3.6.3.3 Debug ............. This section controls the debugging options of AdaControl. * "Debug messages". This sets the "-d" option. *Note Verbose and debug mode::. * "Halt on error". This sets the "-x" option. *Note Exit on error::. 3.6.3.4 Output .............. This section offers options that control where and how the output of AdaControl is displayed. * "Display only errors". This sets the "-E" option. *Note Treatment of warnings::. * "Warnings as errors". This sets the "-e" option. *Note Treatment of warnings::. * "Statistics". This sets the "-S" option from a pull-down menu. *Note Control kinds and report messages::. * "Send results to GPS". When checked (default), the output of AdaControl is sent to the "locations" window of GPS. * "Send results to File". When checked, the output of AdaControl is sent to the file indicated in the box below. * "Send results to File and GPS". When checked, the output of AdaControl is sent to the file indicated in the box below, and the content of the file is then automatically reloaded in the "locations" window of GPS. If this option is set, the file format is always "Gnat" (the file format option is ignored). * "File name". This is the name of the file that will contain the results when sent to "File" or "File and GPS". If the results are sent to "File" and the file exists, AdaControl will ask for the permission to overwrite it. If the results are sent to "File and GPS", the result file is always overriden without asking. * "File format". This is a pull-down menu that allows you to select the desired format when output is directed to a file ("-F" option). *Note Control kinds and report messages::. 3.6.3.5 ASIS ............ This section controls the ASIS parameters passed to AdaControl. The content of the input field "ASIS options" is used in place of the standard ("-CA -FM") one. Casual users don't need to change the default ASIS options. For more details, *note ASIS options::. 3.6.4 AdaControl preferences ---------------------------- There is an entry for AdaControl in the "edit/preferences" menu: * "delete trees". If this box is checked, tree files are automatically deleted after each run of AdaControl. This avoids having problems with out-of-date tree files, at the expanse of slightly slowing down AdaControl if you run it several times in a row without changing the source files. * "Delete .ali files with tree files". If this box is checked, the ".ali" files in the current directory will also be deleted together with the tree files (either automatically if the previous box is checked, or when the "AdaControl/Delete Tree Files" menu is selected). This is normally what you want, unless the current directory is also used as the object directory for compilations; in the latter case, deleting ".ali" files would cause a full recompilation for the next build of the project. * "Help on rule". This allows you to select how rule specific help (from the "Help/AdaControl/Help on rule" menu) is displayed. If you select "Pop-up", a summary of the rule's purpose and syntax is displayed in a pop-up. If you select "User Guide", the user guide opens in a browser at the page that explains the rule. (Caveat: due to a problem in GPS under Windows, the "User Guide" option may not work at all, or the browser will not find the right anchor; hopefully, this will be fixed in an upcomming release of GPS. No such problem under Linux). * "Use separate categories". If this box is checked, there will be one category (i.e. tree in the locations window) for each rule type or label, otherwise all messages will be grouped under the single category "AdaControl". In practice, this means that with the box checked, messages will be sorted by rules first, then by files, while otherwise, the messages will be sorted by files first, then by rules. In any case, compilation errors appear under the "Compilation" category, final counts under the "Counts summary" category, and statistics under the "Statistics" category. * "Auto save files". If this box is checked, all modified files are automatically saved without asking before running AdaControl. Otherwise, a dialog appears allowing the user to choose which files to save. * "Buttons operate on". This defines the behaviour of the buttons. If "Current File" is selected, the buttons operate on the file being currently edited. If "Root Project" is selected, the buttons operate on all files that are part of the current project. If "Units from List" is selected, the buttons operate on all units from the units file. * "Display AdaControl run". If this box is checked, the command line used to launch AdaControl and the output messages are displayed in the "Messages" window. * "Max allowed error messages". If non zero, run will stop if the number of error messages exceeds this limit. *Note Output limits::. * "Max allowed messages (all kinds)". If non zero, run will stop if the number of error and warning messages exceeds this limit. *Note Output limits::. 3.6.5 AdaControl language ------------------------- If you check "AdaControl" in the "Languages" tab, GPS will recognize files with extension '.aru' as AdaControl rules files, and provide appropriate colorization. 3.6.6 AdaControl help --------------------- The AdaControl User Manual (this manual) and the AdaControl Programmer Manual are available from the "Help/AdaControl" menu of GPS. The "Help on rule" entry displays the list of all rules; if you click on one of them, you get help for the particular rule. Depending on the setting of the "Help on rule" preference (see above), it opens a pop-up that displays the rule(s) purpose and the syntax of its parameters, or opens the user guide at the appropriate location. The "About" entry displays a popup with AdaControl's version number and license condition. 3.6.7 Caveat ------------ GPS may crash when the output of a command is too big (i.e. hundreds of messages with AdaControl). If this happens, use the "preferences" menu to limit the number of messages. 3.7 Running AdaControl from AdaGide =================================== If you want to use AdaControl from AdaGide, make sure you have copied the necessary file into the required place. *Note Installing AdaControl::. Note that AdaGide does not have all the parameterization facilities of sophisticated environments like GPS, but all AdaControl options, like the name of the rules file or the output format, can easily be changed by editing the tool description file 'AdaControl.tdf'. AdaGide now features several AdaControl commands from the "tool" menu: * "AdaControl" runs AdaControl on the currently edited file, with rules taken from the file named 'verif.aru'. * "AdaControl recursive" works like the previous command, with the addition of the "-r" (recursive) option. When used on the main program, it will analyze the whole set of compilation units in the program. * "AdaControl interactive" runs AdaControl on the currently edited file, with a rule asked interactively from a pop-up. * "AdaControl: delete .adt" removes existing tree files from the current directory. This is convenient when AdaControl complains that the tree files are not up-to-date. 3.8 Helpful utilities ===================== This section describe utilities that are handy to use in conjunction with AdaControl. 3.8.1 pfni ---------- The convention used to refer to entities (as described in *note Specifying an Ada entity name::) is very powerful, but it may be difficult to spell out correctly the name of some entities, especially when using the overloaded syntax. 'pfni' (which stands for Print Full Name Image) can be used to get the correct spelling for any Ada entity. The syntax of 'pfni' is: pfni [-sofdq] [-p ] [:] [-- ] ::= | []-[] | : or pfni -h If called with the "-h" option, 'pfni' prints a help message and exits. Otherwise, 'pfni' prints the full name image of all identifiers declared in the indicated unit, unless there is a "-f" (full) option, in which case it prints the full name image of all identifiers (i.e. including those that are used, but not declared, in the unit). The image is printed without overloading information, unless the "-o" option is given. In addition, 'pfni' prints the initial value of variables if there is one, the range of discrete types, and the range of the indices of array types. The is given either as an Ada unit, or as a file name, provided the extension is ".ads" or ".adb" (as in AdaControl). If a span is given, only identifiers within the span are printed. In the first form, the span includes only the indicated line; in the second form, the span includes all lines from to (if omitted, they are taken as the first and last line of the file, respectively). In the third form, the span includes only the place at the specified and . Normally, the source line corresponding to the names is printed above the names. The "-q" (quiet) option suppresses this. If the "-s" option is given (or the unit is a file name with a ".ads" extension), the specification of the unit is processed, otherwise the body is processed. The "-p" option specifies the name of an Emacs project file, and the "-d" option is the debug mode, as for AdaControl itself. ASIS options can be passed, like for AdaControl, after a "--" (but -FS is the default). *Note ASIS options::. As a side usage of 'pfni', if you are calling a subprogram that has several overloadings and you are not sure which one is called, use 'pfni' with the "-o" option on that line: the program will tell you the full name and profile of the called subprogram. 3.8.2 makepat.sed ----------------- This file (provided in the "src" directory) is a sed script that transforms a text file into a set of correponding regular expressions. It is useful to generate model header files. *Note Header_Comments::. 3.8.3 unrepr.sed ---------------- This file (provided in the "src" directory) is a sed script that comments out all representation clauses. It is typically useful if you use a different compiler that accepts representation clauses not supported by GNAT. Typically, you would copy all your sources in a different directory, copy "unrepr.sed" in that directory, then run: sed -i -f unrepr.sed *.ads *.adb You can now run AdaControl on the patched files. Of course, you won't be able to check rules related to representation clauses any more... Note that the script adds "--UNREPR " to all representation clauses. Its effect can thus easily be undone with the following commad: sed -i -e "s/--UNREPR //" *.ads *.adb 3.9 Optimizing Adacontrol ========================= There are many factors that may influence dramatically the speed of AdaControl when processing many units. For example, on our canonical test (same controls, same units), the extreme points for execution time were 111s. vs 13s.! Unfortunately, this seems to depend on a number of parameters that are beyond AdaControl's control, like the relative speed of the CPU to the speed of the hard-disk, or the caching strategy of the file system. This section will give some hints that may help you increase the speed of AdaControl, but it will not change the output of the program; you don't really need to read it if you just use AdaControl occasionnally. This section is concerned only with the GNAT implementation of ASIS; other implementations work differently. Bear in mind that the best strategy depends heavily on how your program is organized, and on the particular OS and hardware you are using. Therefore, no general rule can be given, you'll have to experiment yourself. Hint: if you specify the "-v" option to AdaControl, it will print in the end the elapsed time for running the tests; this is very helpful to make timing comparisons. Note: all options described in this section are ASIS options, i.e. they must appear last on the command line, after a "--". 3.9.1 Tree files and the ASIS context ------------------------------------- Since AdaControl is an ASIS application, it is useful to explain here how ASIS works. ASIS (and therefore AdaControl) works on a set of units constituting a "context". Any reference to an Ada entity which is not in the context (nor automatically added, see below) will be ignored; especially, if you specify to AdaControl the name of a unit which is not included in the current context, the unit will simply not be processed. ASIS works by exploring tree files (same name as the corresponding Ada unit, with a ".adt" extension), which are "predigested" views of the corresponding Ada units. By default, the tree files are generated automatically when needed, and kept after each run, so that subsequent runs do not have to recreate them. A context in ASIS-for-Gnat is a set of tree files. Which trees are part of the context is defined by the "-C" option: * -C1 Only one tree makes up the context. The name of the tree file must follow the option. * -CN Several explicit trees make up the context. The name of the tree files must follow the option. * -CA All available trees make up the context. These are the tree files found in the current directory, and in any directory given with a "-T" option (which works like the "-I" option, but for tree files instead of source files). The "-F" option specifies what to do if the program tries to access an Ada unit which is not part of the context: * -FT Only consider tree files, do not attempt to compile units on-the-fly * -FS Always compile units on-the-fly, ignore existing tree files * -FM Compile on-the-fly units for which there is no already existing tree file Note that "-FT" is the only allowed mode, and must be specified, with the "-C1" and "-CN" options. The default combination used by AdaControl is "-CA -FM". 3.9.2 Generating tree files manually ------------------------------------ It is also possible to generate the tree files manually before running AdaControl. Although this mode of operation is less practical, it is recommended by AdaCore for any ASIS tool that deals with many compilation units. Some reasons why you might want to generate the tree files manually are: * Your project uses GNAT project files, but you don't want to run AdaControl from GPS; * Your project has several source directories (ASIS had problems with ADA_INCLUDE_PATH, until releases dated later than Sept. 1st, 2006). Note that an alternative solution is to specify source directories with the -I option; * It is faster to generate tree files once than to use "compile on the fly" mode. To generate tree files manually, simply recompile your project with the "-gnatct" option. This option can be passed to 'gnatmake' normally. Of course, you will need all other options needed by your project (like the "-P" option if you are using GNAT project files). Tree files may be copied into a different directory if you don't want your current directory to be cluttered by them. In this case, use the "-T" ASIS option to indicate the directory where the tree files are located. If you chose to generate the tree files manually, you may want to specify the "-FT" ASIS option (see above) to prevent from accidental automatic recompilation. 3.9.3 Choosing an appropriate combination of options ---------------------------------------------------- In order to optimize the use of AdaControl, it is important to remember that reading tree files is a time-consuming operation. On the other hand, a single tree file contains not only information for the corresponding unit, but also for the specifications of all units that the given unit depends on. Moreover, our measures showed that reading an existing tree file may be slower than compiling the corresponding unit on-the-fly (but once again, YMMV). Here are some hints to help you find the most efficient combination of options. * If you want to run AdaControl on all units of your program, use the "-D" option to create a file containing the list of all required units, then use this file as an indirect file. Using the the "-r" option (recursive mode) of AdaControl implies an extra pass over the whole program tree to determine the necessary units. * If you have not disabled any rule (and have many messages), specifying the "-i" option (ignore disabling) saves AdaControl the burden of checking whether rules are disabled, which can result in a sensible speed-up. * Avoid having unnecessary tree files. All tree files in the context are read by ASIS, even if they are not later used. If you don't want to run AdaControl on the whole project, deleting tree files from a previous run can save a lot of time. * When using an indirect file, the order in which units are given may influence the speed of the program. As a rule of thumb, units that are closely related should appear close to each other in the file. A good starting point is to sort the file in alphabetical order: this way, child units will appear immediately after their parent. You can then reorder units, and measure if it has a significant effect on speed. * If you want to check a unit individually, try using the "-C1" option (especially if the current directory contains many tree files from previous runs). Remember that you must specify the unit to check to AdaControl, and the tree file to ASIS. I.e., if you want to check the unit "Example", the command line should look like: adactl -f rules_file.aru example -- -FT -C1 example.adt provided the tree file already exists. * For each strategy, first run AdaControl with the default options (which will create all necessary tree files). Compare execution time with the one you get with "-FT" and "-FS". This will tell you if compiling on-the-fly is more efficient than loading tree files, or not. 3.10 In case of trouble ======================= 3.10.1 Known issues ------------------- If you are using an old version of GNAT and your project includes source files located in several directories, the ADA_INCLUDE_PATH environment variable may not be considered by ASIS, resulting in error messages that tell you that the bodies of some units have not been found (and hence have not been processed). This problem has been fixed in GNAT dated later than Sept. 1st, 2006. If this happens, either provide your source directories as "-I" options (*note ASIS options::), or generate the tree files manually (*note Generating tree files manually::). Note that this problem does not happen if you are using Emacs project files (*note Project files::), nor if you are running AdaControl from GPS. 3.10.2 AdaControl or ASIS failure --------------------------------- Like any sophisticated piece of software, AdaControl may fail when encountering some special case of construct. ASIS may also fail occasionnally; actually, we discovered several ASIS bugs during the development of AdaControl. These were reported to ACT, and have been corrected in the wavefront version of GNAT - but you may be using an earlier version. In this case, try to upgrade to a newer version of ASIS. If an AdaControl or ASIS problem is not yet solved, AdaControl is designed in such a way that an occasionnal bug won't prevent you from using it. If AdaControl detects an unexpected exception during the processing of a unit (an ASIS error or an internal error), it will abandon the unit, clean up everything, and go on processing the remaining units. This way, an error due to a special case in a unit will not affect the processing of other units. AdaControl will return a Status of 10 in this case. However, if it is run with the "-x" option (eXit on error), it will stop immediately, and no further processing will happen. If you don't want the garbage from a failing rule to pollute your report, you may chose to disable the rule for the unit that has a problem. *Note Inhibit command::. If you encounter a problem while using AdaControl, you are very welcome to report it through our Mantis bug tracking system (https://sourceforge.net/apps/mantisbt/adacontrol/my_view_page.php) (under Windows, you can click on "Report problem" in the AdaControl Start menu). Please include the exact control and the unit that caused the problem, as well as the captured output of the program (with "-dx" option). 4 Command language reference **************************** AdaControl is about controlling rules. Rules are built in AdaControl; each rule has a name, and may require parameters. For the complete description of each rule, *note Rules reference::. To run AdaControl, you need to define which rules you want to apply to your Ada units, what are the parameters, etc. In addition, you may want to define various things, like the file where the results should go, the output format, etc. AdaControl defines a small command language which is used to describe how you want to process your units. Commands can be specified either on the command line or in a file, that we call here a rules file. Commands can also be given interactively; *Note Interactive mode::. 4.1 General =========== The command language is not case-sensitive, i.e. the case of the keywords, rule names, and parameters is not significant. The layout of commands is free (i.e. a command can extend over several lines, and spaces are freely allowed between syntactic elements). Comments are allowed in and between commands. Comments begin with a "#" or a "--", and extend to the end of the line. Since wide characters are allowed in Ada programs, AdaControl accepts wide characters in commands as well. With GNAT, the encoding scheme is Hex ESC encoding (see the GNAT User-Guide/Reference-Manual). This is the prefered method, since few people require wide characters in programs anyway, and that keeping the default bracket encoding would not conveniently allow brackets for regular expressions, like those used by some rules. *Note Syntax of regular expressions::. If a syntax error is encountered in a command, an appropriate error message is output, and analysis of the rules file continues in order to output all errors, but no analysis of user code will be performed. 4.2 Controls ============ A control command is a command that declares one (or several) controls. A control defines how a rule is applied to Ada units. The syntax of a control command is as follows: ::= [