Dear all,

this is my take on Usage advice. I've scanned the complete RM NOTEs and extracted what I deem (in some way or another) to be some kind of advice.

YMMV about what I selected. Most probably I missed some NOTEs that you might consider.

At least, this may serve as a basis for discussion.

I've used the RM version 2022 with differences to 2012 TC1 in case you want to undo those last changes of NOTEs under Usage header.

Take care
Christoph
-------- Weitergeleitete Nachricht --------
Betreff:        First attempt for AI22-0097-1
Datum:  Sat, 16 Mar 2024 11:05:52 +0100
Von:    Christoph & Ursula Grein <[email protected]>
An:     [email protected]

These are my findings in the clauses 1 to 3....
Title: AI22-0097-1/01

Modify 1.1.4(19):

{Usage}

[NOTE 1  ] The syntax rules describing structured constructs are presented in a form that corresponds to the recommended paragraphing. For example, an if_statement is defined as:

Modify 1.1.4(21):

[NOTE 2  ] The line breaks and indentation in the syntax rules indicate the recommended line breaks and indentation in the corresponding constructs. The preferred places for other line breaks are after semicolons.

Modify 3.2.2(13/5):

{Usage}

A scalar_constraint can may be applied to a subtype of an appropriate scalar type (see 3.5, 3.5.9, and J.3), even if the subtype is already constrained. On the other hand, a composite_constraint can may be applied to a composite subtype (or an access-to-composite subtype) only if the composite subtype is unconstrained (see 3.6.1 and 3.7.1).

Modify 3.5.1(12):

{Usage}

[NOTE  ] If an enumeration literal occurs in a context that does not otherwise suffice to determine the type of the literal, then qualification by the name of the enumeration type is one way to resolve the ambiguity (see 4.7).

Add after 3.5.2(5/3):

Usage

A conventional character set such as EBCDIC can be declared as a character type; the internal codes of the characters can be specified by an enumeration_representation_clause as explained in 13.4.

Delete 3.5.2(9/5):

NOTE 2   A conventional character set such as EBCDIC can be declared as a character type; the internal codes of the characters can be specified by an enumeration_representation_clause as explained in 13.4.

Add after 3.5.5(8):

Usage

For a subtype of a discrete type, the result delivered by the attribute Val can be outside might not belong to the subtype; similarly, the actual parameter of the attribute Pos can also be outside need not belong to the subtype. The following relations are satisfied (in the absence of an exception) by these attributes:

S'Val(S'Pos(X)) = X
S'Pos(S'Val(N)) = N

Delete 3.5.5(12/5):

NOTE 4   For a subtype of a discrete type, the result delivered by the attribute Val can be outside the subtype; similarly, the actual parameter of the attribute Pos can also be outside the subtype. The following relations are satisfied (in the absence of an exception) by these attributes:

Delete 3.5.5(13):

S'Val(S'Pos(X)) = X
S'Pos(S'Val(N)) = N

Add after 3.5.10(14):

Usage

S'Scale is not always the same as S'Aft for a decimal subtype; for example, if S'Delta = 1.0 then S'Aft is 1 while S'Scale is 0.

Delete 3.5.10(16):

NOTE 2   S'Scale is not always the same as S'Aft for a decimal subtype; for example, if S'Delta = 1.0 then S'Aft is 1 while S'Scale is 0.

Modify 3.7(28):

{Usage}

[NOTE 1  ] If a discriminated type has default_expressions for its discriminants, then unconstrained variables of the type are permitted, and the values of the discriminants can be changed by an assignment to such a variable. If defaults are not provided for the discriminants, then all variables of the type are constrained, either by explicit constraint or by their initial value; the values of the discriminants of such a variable cannot be changed after initialization.

Add after 3.9.1(5):

Usage

When an extension is declared immediately within a body, primitive subprograms are inherited and are overridable, but new primitive subprograms cannot be added.

Delete 3.9.1(7/2):

NOTE 2 When an extension is declared immediately within a body, primitive subprograms are inherited and are overridable, but new primitive subprograms cannot be added.

Add after 3.10.2(32.6/5):

Usage

The Access attribute for subprograms and parameters of an anonymous access-to-subprogram type can be used may together be used to implement “downward closures” — that is, to pass a more-nested subprogram as a parameter to a less-nested subprogram, as can might be appropriate for an iterator abstraction or numerical integration. Downward closures can also be implemented using generic formal subprograms (see 12.6). Unlike for objects, there is no Note that Unchecked_Access attribute is not allowed for subprograms.

Using Note that using an access-to-class-wide tagged type with a dispatching operation is a potentially more structured alternative to using an access-to-subprogram type.

Delete 3.10.2(37/5):

NOTE 5 The Access attribute for subprograms and parameters of an anonymous access-to-subprogram type can be used together to implement “downward closures” — that is, to pass a more-nested subprogram as a parameter to a less-nested subprogram, as can be appropriate for an iterator abstraction or numerical integration. Downward closures can also be implemented using generic formal subprograms (see 12.6). Unlike for objects, there is no Unchecked_Access attribute for subprograms.

Delete 3.10.2(38/5):

NOTE 6 Using an access-to-class-wide tagged type with a dispatching operation is a potentially more structured alternative to using an access-to-subprogram type.


Modify 4.1.6(18/4):

{Usage}

[NOTE  ] The Constant_Indexing and Variable_Indexing aspects cannot be redefined when inherited for a derived type, but the functions that they denote can be modified by overriding or overloading.

[This sounds like a weak advice.]

Modify 4.3.3(33/5):

{Usage}

[NOTE 1  ] In an array_aggregate delimited by parentheses, positional notation can may only be used with two or more _expression_s; a single _expression_ in parentheses is interpreted as a parenthesized _expression_. An array_aggregate delimited by square brackets can may be used to specify an array with a single component.

[An advice to use the new syntax, which might be reworded like: It is recommended to use square brackets...]

Modify 4.7(5/5):

{Usage}

[NOTE  ] When a given context does not uniquely identify an expected type, a qualified_expression can be used to do so. In particular, if an overloaded name or aggregate is passed to an overloaded subprogram, it can might be necessary to qualify the operand to resolve its type.

Modify 5.4(14/5):

{Usage}

[NOTE  ] The execution of a case_statement chooses one and only one alternative. Qualification of the _expression_ of a case_statement by a static subtype can often be used to limit the number of choices that can need be given explicitly.

Add after 5.5(12/5):

Usage

No separate An object_declaration is expected should not be given for a loop parameter, since the loop parameter is automatically declared by the loop_parameter_specification. The scope of a loop parameter extends from the loop_parameter_specification to the end of the loop_statement, and the visibility rules are such that a loop parameter is only visible within the sequence_of_statements of the loop.

Delete 5.5(14/5):

NOTE 2  No separate object_declaration is expected for a loop parameter, since the loop parameter is automatically declared by the loop_parameter_specification. The scope of a loop parameter extends from the loop_parameter_specification to the end of the loop_statement, and the visibility rules are such that a loop parameter is only visible within the sequence_of_statements of the loop.

[I'm much in doubt this is an advice.]

Add after 6.1.1(42/5):

Usage

For an example of the use of these aspects and attributes, see the Streams Subsystem definitions in 13.13.1.

Delete 6.1.1(44/5):

NOTE 2 For an example of the use of these aspects and attributes, see the Streams Subsystem definitions in 13.13.1.

[NOTE 1 doesn't seem to be an advice.]

Modify 6.1.2(44/5):

{Usage}

[NOTE  ] For an example of the use of these aspects, see the Vector container definition in A.18.2.

[Are examples an advice?]

Modify 7.3.3(12/5):

{Usage}

[NOTE  ] For an example of the use of this aspect, see the Vector container definition in A.18.2.

Modify 7.3.4(32/5):

{Usage}

[NOTE  ] For an example of the use of these aspects, see the Vector container definition in A.18.2.

Add after 8.5(3):

Usage

A subtype defined without any additional constraint can be used to achieve the effect of renaming another subtype (including a task or protected subtype) as in

   subtype Mode is Ada.Text_IO.File_Mode;

Delete 8.5(6):

NOTE 3  A subtype defined without any additional constraint can be used to achieve the effect of renaming another subtype (including a task or protected subtype) as in

Delete 8.5(7):

   subtype Mode is Ada.Text_IO.File_Mode;

[Very weak advice.]

Add after 9.5.1(18/5):

Usage

The aspect Nonblocking can be specified True on the definition of a protected unit in order to reject most attempts to use potentially blocking operations within the protected unit (see 9.5). The pragma Detect_Blocking can may be used to ensure that any remaining all executions of potentially blocking operations during a protected action raise Program_Error. See H.5.

Delete 9.5.1(23/5):

NOTE 5  The aspect Nonblocking can be specified True on the definition of a protected unit in order to reject most attempts to use potentially blocking operations within the protected unit (see 9.5). The pragma Detect_Blocking can be used to ensure that any remaining executions of potentially blocking operations during a protected action raise Program_Error. See H.5.

Add after 9.6.1(89/2):

Usage

Calling Split on the results of subtracting Duration(Local_Time_Offset*60) from Clock provides the components (hours, minutes, and so on) of the UTC time. In the United States, for example, Local_Time_Offset will generally be negative.

Delete 9.6.1(91/5):

NOTE 2  Calling Split on the results of subtracting Duration(Local_Time_Offset*60) from Clock provides the components (hours, minutes, and so on) of the UTC time. In the United States, for example, Local_Time_Offset will generally be negative.

[I think (91.a/5) should be promoted to the RM because it has additional advice.]

Modify 11.5(29/5):

{Usage}

[NOTE 1  ] There is no guarantee that a suppressed check is actually removed; hence a pragma Suppress is useful only to improve should be used only for efficiency reasons.

Modify 11.5(29.1/2):

[NOTE 2  ] It is possible to give both a pragma Suppress and Unsuppress for the same check immediately within the same declarative_part. In that case, the last pragma given determines whether or not the check is suppressed. Similarly, it is possible to resuppress a check which has been unsuppressed by giving a pragma Suppress in an inner declarative region.

[Also without "should" this looks like an advice.]

Modify 13.3(20):

{Usage}

[NOTE 1  ] The specification of a link name with the Link_Name aspect (see B.1) for a subprogram or object is an alternative to explicit specification of its link-time address, allowing a link-time directive to place the subprogram or object within memory.

[I'm very much in doubt this is advice.]

Modify 13.11.3(9/5):

{Usage}

[NOTE 1  ] Default_Storage_Pool can may be used with restrictions No_Coextensions and No_Access_Parameter_Allocators (see H.4) to ensure that all allocators use the default pool.

Modify 13.11.4(33/5):

{Usage}

[NOTE 1  ] A user-defined storage pool type that supports subpools can be implemented by extending the Root_Storage_Pool_With_Subpools type, and overriding the primitive subprograms Create_Subpool, Allocate_From_Subpool, and Deallocate_Subpool. Create_Subpool is expected to should call Set_Pool_Of_Subpool before returning the subpool handle. To make use of such a pool, a user can would declare an object of the type extension, can use it to define the Storage_Pool attribute of one or more access types, and then can invoke call Create_Subpool to obtain subpool handles associated with the pool.

Modify 13.11.4(34/5):

[NOTE 2  ] A user-defined storage pool type that supports subpools can may define additional subpool constructors similar to Create_Subpool (these typically will have additional parameters).

Modify 13.11.4(35/5):

[NOTE 3  ] The pool implementor can should override Default_Subpool_For_Pool if they want the pool is to support a default subpool for the pool. The implementor can override Deallocate if individual object reclamation is to be supported, and can override Storage_Size if there is some limit on the total size of the storage pool. The implementor can override Initialize and Finalize if there is any desire need for nontrivial initialization and finalization for the pool as a whole. For example, Finalize can might reclaim blocks of storage that are allocated over and above the space occupied by the pool object itself. The pool implementor can may extend the Root_Subpool type as necessary to carry additional information with each subpool provided by Create_Subpool.

Modify 13.12(16/2):

{Usage}

[NOTE 1  ] Restrictions intended to facilitate the construction of efficient tasking run-time systems are defined in D.7. Restrictions intended for use when constructing high integrity systems are defined in H.4.

[A hint where to find advice for certain cases.]

Modify 13.13.1(38):

{Usage}

[NOTE 1  ] See A.12.1, “The Package Streams.Stream_IO” for an example of extending type Root_Stream_Type.

[Is an example an advice? However, I cannot see in A.12.1 a type extension of Root_Stream_Type. There is something wrong.]

Modify 13.13.1(39/2):

[NOTE 2  ] If the end of stream has been reached, and Item'First is Stream_Element_Offset'First, Read will raise Constraint_Error.

[This does not sound like an advice. However, (39.a/2) does sound like an advice and should be promoted to the RM proper:
(39.a/2) Ramification: Thus, Stream_Element_Arrays should start at 0 or 1, not Stream_Element_Offset'First.]

Modify 13.13.2(57/5):

{Usage}

[NOTE 1  ] For a definite subtype S of a type T, only T'Write and T'Read are necessary needed to pass an arbitrary value of the subtype through a stream. For an indefinite subtype S of a type T, T'Output and T'Input will normally be necessary needed, since T'Write and T'Read do not pass bounds, discriminants, or tags.

[This looks like a weak advice.]

Modify A.4.3(107/5):

{Usage}

[NOTE 1  ] In the Index and Count functions taking Pattern and Mapping parameters, for there to be a match, the actual String parameter passed to Pattern can contain only should comprise characters occurring as target characters of the mapping. Otherwise, the pattern will not match..

Modify A.4.3(108):

[NOTE 2  ] In the Insert subprograms, inserting at the end of a string is obtained by passing Source'Last+1 as the Before parameter.

[Both sound like a weak advice.]

Modify A.4.11(108/3):

{Usage}

[NOTE  ] A BOM (Byte-Order Mark, code position 16#FEFF#) can be included in a file or other entity to indicate the encoding; it is skipped when decoding. Typically, only the first line of a file or other entity contains a BOM. When decoding, the Encoding function can be called on the first line to determine the encoding; this encoding will then be used in subsequent calls to Decode to convert all of the lines to an internal format.

Modify A.18.2(263/5):

{Usage}

[NOTE 1  ] All elements of a vector occupy locations in the internal array. If a sparse container is required, a Hashed_Map can should be used rather than a vector.

Add after B.1(41/5):

Usage

The Convention aspect in combination with the Import aspect indicates the conventions for accessing external entities. It is possible that the actual entity is written in assembly language, but reflects the conventions of a particular language. For example, with Convention => Ada can be used to interface to an assembly language routine that obeys the Ada compiler's calling conventions.

To obtain “call-back” to an Ada subprogram from a foreign language environment, the Convention aspect can should be specified both for the access-to-subprogram type and the specific subprogram(s) to which 'Access is applied.

Delete B.1(43/3):

NOTE 2  The Convention aspect in combination with the Import aspect indicates the conventions for accessing external entities. It is possible that the actual entity is written in assembly language, but reflects the conventions of a particular language. For example, with Convention => Ada can be used to interface to an assembly language routine that obeys the Ada compiler's calling conventions.

Delete B.1(44/5):

NOTE 3  To obtain “call-back” to an Ada subprogram from a foreign language environment, the Convention aspect can be specified both for the access-to-subprogram type and the specific subprogram(s) to which 'Access is applied.

Modify B.3(72):

{Usage}

[NOTE 1  ] Values of type char_array are not implicitly terminated with nul. If a char_array is to be passed as a parameter to an imported C function requiring nul termination, it is the programmer's responsibility to obtain this effect.

Modify B.3(73):

[NOTE 2  ] To obtain the effect of C's sizeof(item_type), where Item_Type is the corresponding Ada type, evaluate the _expression_: size_t(Item_Type'Size/CHAR_BIT).

Modify B.3(75/4):

[NOTE 3  ] A variadic C function can correspond to several Ada subprograms, taking various specific numbers and types of parameters.

Modify B.3.1(58/5):

{Usage}

[NOTE  ] New_Char_Array and New_String can might be implemented either through the allocation function from the C environment (“malloc”) or through Ada dynamic memory allocation (“new”). The key points are 

Add after C.7.2(30.1/2):

Usage

The result of the Reference function should be used with care; it is always safe to use that result in the task body whose attribute is being accessed. However, when the result is being used by another task, the programmer will want to must make sure that the task whose attribute is being accessed is not yet terminated. Failing to do so can could make the program execution erroneous.

Delete C.7.2(32/5):

NOTE 2  The result of the Reference function is always safe to use in the task body whose attribute is being accessed. However, when the result is being used by another task, the programmer will want to make sure that the task whose attribute is being accessed is not yet terminated. Failing to do so can make the program execution erroneous.

Add after D(3):

Usage

The metrics do not cover the whole language; they are limited to features that are specified in Annex C, “Systems Programming” and in this Annex. The metrics are intended to provide guidance to potential users as to whether a particular implementation of such a feature is going to be adequate for a particular real-time application. As such, the metrics are aimed at known implementation choices that can result in significant performance differences.

Delete D(5):

NOTE 2  The metrics do not cover the whole language; they are limited to features that are specified in Annex C, “Systems Programming” and in this Annex. The metrics are intended to provide guidance to potential users as to whether a particular implementation of such a feature is going to be adequate for a particular real-time application. As such, the metrics are aimed at known implementation choices that can result in significant performance differences.

Add after D.3(17):

Usage

When specifying the ceiling of a protected object, a correct one should choose a value is one that is at least as high as the highest active priority at which tasks can be executing when they call protected operations of that object. In determining this value the following factors, which can affect active priority, are relevant should be considered: the effect of Set_Priority, nested protected operations, entry calls, task activation, and other implementation-defined factors.

Attaching a protected procedure whose ceiling is below the interrupt hardware priority to an interrupt causes the execution of the program to be erroneous (see C.3.1).

Delete D.3(21/5):

NOTE 4  When specifying the ceiling of a protected object, a correct value is one that is at least as high as the highest active priority at which tasks can be executing when they call protected operations of that object. In determining this value the following factors, which can affect active priority, are relevant: the effect of Set_Priority, nested protected operations, entry calls, task activation, and other implementation-defined factors.

Delete D.3(22):

NOTE 5  Attaching a protected procedure whose ceiling is below the interrupt hardware priority to an interrupt causes the execution of the program to be erroneous (see C.3.1).

[An advice not to do something.]

Add after D.5.1(14):

Usage

Changing the priorities of a set of tasks can be performed by a series of calls to Set_Priority for each task separately. This can be done For this to work reliably, it should be done within a protected operation that has high enough ceiling priority to guarantee that the operation completes without being preempted by any of the affected tasks.

Delete D.5.1(19/5):

NOTE 5  Changing the priorities of a set of tasks can be performed by a series of calls to Set_Priority for each task separately. This can be done reliably within a protected operation that has high enough ceiling priority to guarantee that the operation completes without being preempted by any of the affected tasks.

Modify F.2(17):

{Usage}

[NOTE  ] The effect of division yielding a quotient with control over rounding versus truncation is obtained by applying either the function attribute Quotient_Type Round or the conversion Quotient_Type to the _expression_ Dividend/Divisor.

[A cookbook advice.]

Modify A.H(6/5):

{Usage}

[NOTE  ] The Valid attribute (see 13.9.2) is also useful in addressing these needs, to avoid problems that can could otherwise arise from scalars that have values outside their declared range constraints.


Reply via email to