Version 1.1 of acs/ac-00058.txt

Unformatted version of acs/ac-00058.txt version 1.1
Other versions for file acs/ac-00058.txt

!standard C.8(01)          03-07-22 AC95-00058/01
!class amendment 03-07-22
!status received no action 03-07-22
!status received 03-04-14
!subject Pragma Unreferenced
!summary
!appendix

From: Martin Dowie
Sent: Monday, April 14, 2003  6:56 AM

I've been making use of the GNAT specific pragma "Unreferenced"
recently. For those who haven't used it it simply indicates to
the compiler that while an entity is declared is not expected to
be used. e.g.

   procedure Foo (I : Integer) is
      pragma Unreferenced (I);
   begin
      Put_Line ("Called Foo"); -- No reference to "I"
   end Foo;

During compilation no warning is then given about the parameter "I"
not being referenced within "Foo". Conversly if "Foo" is altered
such that "I" *is* then but the pragma not removed then another
warning is issued. This is not limited to parameters but to
any entity.

Unused parameters can be quite common in test stubs and also in
callback routines and searching through build listings to spot the
expected 'not referenced' from the real errors can be time consuming
and error prone.

This looks to me to be a candidate for making standard.

Any thoughts?

****************************************************************

From: Tucker Taft
Sent: Monday, April 14, 2003  3:22 PM

I would agree this sounds like a useful and simple
pragma, that will enhance static detection of errors.

****************************************************************

From: Nick Roberts
Sent: Monday, April 14, 2003  4:02 PM

I agree this pragma would be very useful and should be added at the next
revision.

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  3:38 AM

As it is often said that a poor proposal is better than no proposal, I offer
this effort.

The one thing that struck me was when looking through the ARM, I couldn't see
any other similar pragma - one that acts on objects and subprograms and,
perhaps more importantly, deals with *warnings*, so I have left the heading
number and placement to the ARG (should it be approved).

Also, I wasn't entirely sure whether point 5 should be placed under Legality
Rules or some other section.


!standard L

!subject pragma Unreferenced

!summary

A standard "unreferenced" pragma is proposed which takes one or more,
local_names as parameters. This pragma indicates that each of the local_name is
not expected to be referenced within the current scope.

!problem

It is common for test stub subprograms and for callbacks not to use all the
parameters passed to them. This pragma allows the programmer to specifically
indicate that they do not expect an entity to be referenced within the
subprogram.

!proposal

The form of the pragma Unreferenced is as follows:

    pragma Unreferenced(local_name {,local_name});

  A pragma Unreferenced is only allowed in a declarative_part. The local_name
  of a pragma Unreferenced shall resolve to either a subprogram name or an
  object_declaration.

!wording

Insert section:

A.B.C Pragma Unreferenced

An occurrence of a pragma Unreferenced identifies a set of subprograms or
objects which are declared but intentionally unused. The purpose of such a
pragma is to help identify entities that are declared and intended to be used
but are erroneously not referenced.

Syntax

The form of a pragma Unreferenced is as follows:

pragma Unreferenced(local_name {, local_name});

Legality Rules

4 A pragma Unreferenced is only allowed within a declarative_part. Each
local_name shall statically denote the declaration of an object or subprogram.

5 If local_name identifies more than one matching homonym in the current scope,
then the entity most recently declared is the one to which the pragma applies.

Static Semantics

6 A pragma Unreferenced indicates to an implementation that the entity is
deliberately not referenced within the current scope.

Dynamic Semantics

7 Execution of a pragma Unreferenced has no effect.


Insert into Annex L replacing <> with the appropriate cross reference:

    pragma Unreferenced(local_name {,local_name}); -- <A.B.C>

!discussion

This AI attempts to standardize the Unreferenced pragma already supported by
various implementations.

!example

    procedure Log (I : Integer) is
        pragma Unreferenced (I);
    begin
       Put_Line ("Test stub for Log called");
    end Log;

****************************************************************

From: Jean-Pierre Rosen
Sent: Tuesday, April 15, 2003  4:22 AM

> Legality Rules

I would add:
It is illegal to reference an entity denoted by a pragma Unreferenced.

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  4:59 AM

>I would add:
>It is illegal to reference an entity denoted by a pragma Unreferenced.

Does the word 'illegal' imply an error should be raised rather than
a warning (as currently implemented by GNAT)?

****************************************************************

From: Jean-Pierre Rosen
Sent: Tuesday, April 15, 2003  7:58 AM

Definitely. See the definition of "illegal" in the RM ;-)
BTW: it is not only useful, it is the only way you can write a test for it...

****************************************************************

From: Tucker Taft
Sent: Tuesday, April 15, 2003  8:33 AM

Illegal means a compile-time error (not "raised" at run-time and
not a warning).  If you explicitly insert such a pragma,
I believe a violation of the pragma should
be considered an error.  I realize it is just a warning
in GNAT now, but I don't think we want to standardize that
behavior.  Chances are, someone who has gone to the trouble
of using pragma Unreferenced with GNAT is probably also activitating
the "warnings are errors" flag as well, so I don't think there
are a lot of folks out there who would be annoyed if this
became an error, rather than a warning.

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  9:10 AM

Ok - I just had it in my mind that existing behaviour is
probably easier to be agreed on. But an error suites me
fine.

I guess there is always the arguement that they should
have been aware that they were using a non-portable
feature anyway.

****************************************************************

From: Tucker Taft
Sent: Tuesday, April 15, 2003  4:49 AM

Thanks for writing this up.

What happens if there are subunit stubs ("... is separate;")
within the scope of an entity having a pragma Unreferenced?
Does the implied restriction on reference apply to the
corresponding subunits?  (I presume it does.)

I would think it would be *illegal* to reference
an entity named in a pragma Unreferenced.  I see
no reason to make it only a warning.  On the other
hand, the implementation might have a warning when
it detects an entity is never referenced.  Presumably
this pragma suppresses that warning for the named
entity.  Such a warning will be trickier to implement
in the presence of subunit stubs, unless all subunits
are "inlined" at the point of the stub (which I believe
they are in GNAT).

Also, does the current GNAT implementation make pragma Unreferenced
apply to the nearest overloading, or to all overloadings
of the given name?  If it only applies to the nearest overloading,
then I would say the pragma must follow immediately after
the declaration of the overloadable if there is more
than one overloading.  Otherwise, it is a maintenance
headache.

****************************************************************

From: Tucker Taft
Sent: Tuesday, April 15, 2003  4:52 AM

One other question -- this might be useful
for names mentioned in "with" clauses.  But
local_name disallows that.  Does GNAT have
any way of specifiying that a with clause
is intended to be unused?

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  5:41 AM

It is also required to be in a declarative_part.

No, GNAT doesn't have a such a feature nor does
it actually give a warning if there is such an
unused unit.

We could always change the proposal to use
'direct_name'(?) instead of 'local_name'.

direct_name would also allow a user defined
operator to be unreferenced, yes?

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  5:21 AM

>Also, does the current GNAT implementation make pragma Unreferenced
>apply to the nearest overloading, or to all overloadings
>of the given name?  If it only applies to the nearest overloading,
>then I would say the pragma must follow immediately after
>the declaration of the overloadable if there is more
>than one overloading.  Otherwise, it is a maintenance
>headache.

Doesn't this section cover the above point?

>> Legality Rules
>>
[snip]
>> 5 If local_name identifies more than one matching homonym in the current
>> scope, then the entity most recently declared is the one to which the pragma
applies.

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  5:33 AM

>Thanks for writing this up.

You're welcome. I can now appreciate how difficult this
all is - this has to come under the 'Easy' classification
but it made me sweat! :-)


>What happens if there are subunit stubs ("... is separate;")
>within the scope of an entity having a pragma Unreferenced?
>Does the implied restriction on reference apply to the
>corresponding subunits?  (I presume it does.)
>
>I would think it would be *illegal* to reference
>an entity named in a pragma Unreferenced.  I see
>no reason to make it only a warning.  On the other
>hand, the implementation might have a warning when
>it detects an entity is never referenced.  Presumably
>this pragma suppresses that warning for the named
>entity.  Such a warning will be trickier to implement
>in the presence of subunit stubs, unless all subunits
>are "inlined" at the point of the stub (which I believe
>they are in GNAT).

ok - the following is what GNAT (3.15p) does:

-- test_unreferenced.adb
procedure Test_Unreferenced is
   C : Boolean := False;
   pragma Unreferenced (C);
   procedure Subunit_Stub (A : Integer; B : Float) is separate;
   pragma Unreferenced (Subunit_Stub);
begin
   null;
end Test_Unreferenced;

-- test_unreferenced-subunit_stub.adb
separate (Test_Unreferenced)

procedure Subunit_Stub (A : Integer; B : Float) is
   pragma Unreferenced (A, B);
begin
   C := True;
end Subunit_Stub;


And it correctly identifies:

'test_unreferenced-subunit_stub.adb:6:04: warning: pragma Unreferenced given
for "C"'

Does this require an extra 'Legality' rule? Or would this already be covered by
the existing scoping rules?

****************************************************************

From: Arnuad Charlet
Sent: Tuesday, April 15, 2003  6:04 AM

> No, GNAT doesn't have a such a feature nor does
> it actually give a warning if there is such an
> unused unit.

Actually it does, when using -gnatwu

The only way to turn off this particular warning is to use
pragma Warnings (Off) as far as I know.

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  6:37 AM

Apologies - I was thinking in terms of language
exensions that would be 'half-inched' rather
than compilation switches.

I shall go and see if '-gnatwu' is worth adding to
my list of de-facto GNAT swithes...

****************************************************************

From: Stephane Barbey
Sent: Tuesday, April 15, 2003  6:44 AM

>One other question -- this might be useful
>for names mentioned in "with" clauses.

I would love it, as in

with my_package_linker_options;
pragma Unreferenced (my_package_linker_options);
with my_package_elaboration_is_required;
pragma Unreferenced (my_package_elaboration_is_required);

Be aware that the pragma Warnings is not allowed in
all organizations... We have to correct the source of
warnings, not shut up the compiler...

****************************************************************

From: Robert A. Duff
Sent: Tuesday, April 15, 2003 11:56 AM

I agree -- it sounds useful.  Note that sometimes a parent package has a
'with' that is intended to be used by all of its children (the parent is
often empty, even).  GNAT warns about this case, even though the thing
is referenced in the children.

> Be aware that the pragma Warnings is not allowed in
> all organizations... We have to correct the source of
> warnings, not shut up the compiler...

That sounds like an unreasonable policy, because it is better to have a
pragma Warnings(Off) with a comment explaining why, than it is to have
some bogus, useless, obfuscatory code inserted just to shut the compiler
up.  I don't think we need to perturb the language design for the
benefit of unreasonable policies.

(It's even better for compilers to avoid bogus warnings, of course, but
that's not always feasible.)

****************************************************************

From: Stephane Barbey
Sent: Tuesday, April 15, 2003 12:54 PM

> Note that sometimes a parent package has a
> 'with' that is intended to be used by all of its children (the parent is
> often empty, even).  GNAT warns about this case, even though the thing
> is referenced in the children.

... and that's the right thing to do. Otherwise you see things
like:

with Starlet;
with Motif;
with X;
package GUI is
end GUI;

... and then people complain why it does take so much time to
compile that little child unit that actually just declare
an exception.


(If you want to be compiler-specific, Gnat even tells you that
a with clause can be moved from the body to the spec, and does
not consider renamings as references, i.e. in

with Starlet;
with Motif;
with X;
package GUI is
   package ST renames Starlet;
end GUI;

the unit Starlet still is a non-used unit -- which sounds
like the right behaviour to me.)

****************************************************************

From: Robert A Duff
Sent: Tuesday, April 15, 2003  7:42 AM

> Doesn't this section cover the above point?

No, I think Tucker was asking for this:

    procedure Foo(...);
    procedure Foo(...); -- Pragma applies to this one.
    X: Integer;
    pragma Unreferenced(Foo);

to be illegal, because another declaration intervenes between the pragma
and what it applies to.  The following wording does not seem to disallow
the above:

> >> Legality Rules
> >>
> [snip]
> >> 5 If local_name identifies more than one matching homonym in the current scope,
> >> then the entity most recently declared is the one to which the pragma applies.

Unless you interpret that to mean that the above Unreferenced(Foo)
refers to X (the "entity most recently declared"), which is surely not
the intent!

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  8:10 AM

Ah! I see what you mean now! :-)

Would a change to:

"...then the homonym most recently declared..."

suffice?

****************************************************************

From: Tucker Taft
Sent: Tuesday, April 15, 2003  8:29 AM

Not really.  The point is that if you have this
rule about a pragma applying to the most recently
declared overloading, then from a maintenance
point of view, it is important that there be
no significant "gap" between the declaration of
the overloading and the pragma.  Otherwise, someone
who doesn't notice the "distant" pragma Unreferenced
may insert another overloading between the intended
overloading and the pragma.  This is what I mean
by a "maintenance headache."

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003 10:36 AM

Is that really a problem?

If there is a new overloading then:
  a) it is referenced - and referencing something (even accidentally)
     marked as 'pragma Unreferenced' would be an error; or

  b) it is unreferenced and the pragma works for it. But this
     leaves the first item unreferenced but without the protection
     of the 'pragma Unreferenced' so a compiler is free to do what
     it currently can do and point this out.

Presumbly, the original 'pragma Unreferenced' was there to ensure
that no such warning could be given - we're not making unreferenced
entities (without the pragma) illegal.

This pragma gives the biggest benefit when used with compilers that
point out unreferenced entities anyway. So hopefully, those that
don't would start to do so if implementing this pragma
(Implementation advice? Tricky I guess...).

****************************************************************

From: Arnaud Charlet
Sent: Tuesday, April 15, 2003  8:36 AM

> the "warnings are errors" flag as well, so I don't think there
> are a lot of folks out there who would be annoyed if this
> became an error, rather than a warning.

Hopefully not, although you never know.

Another issue while we're at studying GNAT semantics on this pragma:

We also use this pragma to mark a variable as never read.
In particular it means that if a variable is only modified, GNAT
will be default issue a warning, and won't if pragma Unreferenced is
specified.

An example to clarify this:

procedure F is
   Ignore : Boolean;
   --  pragma Unreferenced (Ignore);
begin
   Ignore := Function_With_Side_Effect;
end F;

GNAT will generate a warning about Ignore being never read, unless you add a
pragma Unreferenced (Ignore);

****************************************************************

From: Martin Dowie
Sent: Tuesday, April 15, 2003  9:32 AM

>GNAT will generate a warning about Ignore being never read, unless you add a
>pragma Unreferenced (Ignore);

Personally, I'd rather see a different pragma for this use.

Perhaps "pragma Write_Only"? I'm trying hard not to suggest
"pragma Write_Only_Object". Object is just way too overloaded
but perhaps in this case...

****************************************************************

From: Robert A. Duff
Sent: Tuesday, April 15, 2003 10:24 AM

I don't really agree, but I suppose it's a matter of taste.

But I must say, GNAT has precedence here; we should not be making
gratuitous changes to what they have already implemented.  I think
the change that some have suggested, of making a certain warning into an
error, is not gratuitous -- after all, GNAT really couldn't make it
an error since it wasn't standard.  And making it an error is a trivial
change for GNAT, I trust.  But I don't think it's a good idea to fiddle
with the pragma names and so forth -- that would be disruptive to both
GNAT implementers and users.

****************************************************************

From: Tucker Taft
Sent: Tuesday, April 15, 2003 12:41 AM

Hmmmm, this isn't what I presumed "Unreferenced" meant.
I think of "reference" as a general term meaning
roughly the equivalent of "mention."  It sounds like
GNAT is interpreting it as meaning "read."

I somewhat agree with Nick that using "Unreferenced"
to mean "never read" sounds like a misnomer.

****************************************************************

From: Nick Roberts
Sent: Tuesday, April 15, 2003 10:25 AM

I am currently writing up a new proposal. It will take me a few hours or a
day. I hope it will address many of the issues regarding this pragma. I'd
want to avoid duplication of effort, so if anyone else is doing the same
thing, would they please say so (either to me directly
nickroberts@blueyonder.co.uk) or to this mailing list.

****************************************************************

From: Robert Eachus
Sent: Tuesday, April 15, 2003  1:22 PM

I like the idea of standardizing the pragma.

On the issue of applying to the most recent homonym, I would prefer that
it apply to all homonyms like pragma Inline, but I don't see it as a
major issue.  (In fact, I really feel that this issue is not worth all
the electrons that have been spent on it so far.  Applying the pragma to
a locally declared subprogram is going to be rare, and to a locally
overloaded subprogram rarer still.)

With tongue firmly in cheek, and my Norm Cohen mask firmly in place, I
will point out that we need to describe in the AI which attributes read
(RM 3.3(14)) the object for the purposes of this pragma.  Taking off the
mask, I think that any use of the name of the object, subprogram, task
or entry* as a prefix should be illegal.  (This includes attributes,
discriminants, array indices, record components, function return values,
task entries, and so on.)

There is a legality issue we do have to get right.  In the case of a
parameter or object declaration, if it is legal for the compiler not to
materialize the object named in the pragma, is it also legal to
eliminate initialization of the object?  Some cases are trivial.  A task
object still needs to be created.  To see one of the more painful
possible cases think about a dynamically sized array of records where
the calculation of the bounds may have side effects as may the default
initial value for some field of the record.  Note also that exceptions
may be explicit or implicit side effects.

I think the answer has to be that parameters, including out parameters
must be initialized.  Also, the pramga loses some of its usefulness if
explicit initializations with side effects can be eliminated.  I would
like to see elimination of default initial values allowed, but I suspect
that the possibility of task (sub)components would may any such rule too
complex to be worth even proposing.

*It would be nice to allow the pragma to be used within task bodies to
indicate entries that are never accepted.  Extending this to members of
a family of entries, though, is definitely going out where the air is
too rare to support the implementation effort.  (I find it hard to
conceive of cases where I would want to use the pragma with entry
families, in fact, it is hard enough to conceive of uses for entry
families.)

****************************************************************

From: Stephen Leake
Sent: Tuesday, April 15, 2003  1:48 PM

I agree that "Unreferenced" is a misnomer for the GNAT implementation.
I've been using "Unreferenced" since ACT introduced it, and did not
realize it meant "unread" until now; on reading the description the
first time, I thought it meant "no reads, no writes".

On re-reading the GNAT manual, it does say assignment to an
"Unreferenced" object is allowed:

"The left hand side of an assignment does not count as a reference
for the purpose of this pragma. Thus it is fine to assign to an entity
for which pragma Unreferenced is given."

I suspect this was added after the pragma was initially defined, to
allow some special case.

Apparently I have not needed a "no read, no write" pragma.

In the light of Robert Eachus's comments about attributes and default
initialization (all of which are important), it may not be possible to
define a truly "no read, no write" pragma, so perhaps "Unread" is
really what we want.

I would not allow any initialization (implicit or explicit) to be
optimized out; that is what most programmers will unconsciously
expect.

I think the having Unreferenced apply only to the most recent homonym
is a mistake; it should act like "Inline". Having it inconsistent will
cause inadvertant mistakes. If you want it to apply to only one
subprogram, give it a unique name, and use renaming to get the
overloaded name (just like for Inline).

****************************************************************

From: Robert A. Duff
Sent: Tuesday, April 15, 2003  2:18 PM

Regarding Robert Eachus' comments about side-effecting initializations,
my opinion is: pragma Unreferenced should have exactly zero semantic
effect at run time.

****************************************************************

From: Randy Brukardt
Sent: Tuesday, April 15, 2003  2:50 PM

I agree with that; we've already dealt with initializations in other AIs and
I'd hate to reopen that discussion here.

That said, I find this a very suspicious pragma: it's only useful effect is
on warnings (I see no value at all to checking that something is in fact not
used). And warnings are something that have no real standing in the RM. So
we're supposed to add a pragma with no use that we can describe in RM terms?

I'm also very suspicious of the GNAT definition that Unreferenced means
Unread. That would be a relatively difficult check to make in Janus/Ada,
since there is no practical difference between reading and writing of an
object -- all tree nodes look alike. To determine whether something is
written would require determining where in the tree it appears, which is
neither trivial nor desirable. (Unreferenced is much easier, as it applies
to all tree nodes.)

In my experience, most of things that GNAT complains about are 'in out'
parameters that are unwritten. That happens a lot, because Ada doesn't give
us any way to have default values for 'out' parameters (which these really
are supposed to be), and it is common that they are not used in some cases.
Moreover, the message is not really helpful (nor is suppressing it helpful),
because what you really need to know is whether the parameter is ignored
because the parameters say that it is not meaningful, or whether it was
omitted. That requires a more complex condition than any standardized pragma
can give.

So I'm against standardizing this pragma. Its value is for things outside
what the RM can talk about usefully, so I don't think it belongs in the RM.
(Unless you want to define it to be to have unreferenced objects otherwise,
but I think that is too big a change.)

****************************************************************

From: Alexandre E. Kopilovitch
Sent: Tuesday, April 15, 2003  5:37 PM

I'd like to note that here are two kinds of references involved: a reference
to a variable (or identifier) and a reference to the value of a variable.
GNAT's pragma "Unreferenced" is (as it appears) for the latter case, and
perhaps the name "Unreferenced_Value" would be more appropriate for it.
  Although, it is still unclear for me what does this pragma mean for a variable
of controlled type, where an assignment may involve reading of the value.

****************************************************************

From: Robert I. Eachus
Sent: Tuesday, April 15, 2003  7:14 PM

It is becoming increasingly clear to me that if we have a standard
pragma Unreferenced, it should mean that the NAME is not used after the
(full) declaration.

This means that:

...
Junk: Integer := Foo(X);
pragma Unreferenced(Junk);
...
is legal and easy to Understand, while:

X: String := Some_Complex_Function;
pragma Unreferenced(X);
...
if X'First /= 1
then...

is clearly illegal.

One final detail.  I am not sure that we want to leave the class of
things to which pragma Unreferenced can apply unstandardized, or what
the limits should be.  In any case, if pragma Unreferenced is added to
the standard, then all the names listed in the pragma must be legal and
correspond to one or more entities.

Complicated sounding, but what it really comes down to is that the
author expects an error if a pragma Unreferenced fails.  As far as the
author is concerned, a spelling error is just as bad as any other
failure.  So silently ignoring invalid names in a pragma Unreferenced
would be bad juju:

procedure Foo(Some_Long_Variable_Name: in Integer);
pragma Unreferenced(Some_Long_Varaible_Name);
begin
   ...if Some_Long_Variable_Name /= 0 then...
end Foo;

This case must cause some sort of error...

****************************************************************

From: Martin Dowie
Sent: Wednesday, April 16, 2003  2:50 AM

>procedure Foo(Some_Long_Variable_Name: in Integer);
>pragma Unreferenced(Some_Long_Varaible_Name);

Here is another case for insisting that the pragma follow
immediately, as there could very well be an entity in scope
called "Some_Long_Varaible_Name".

I'm rapidly coming to the conclusion that if this pragma
is to be included it should have a different name and not
try to mimic exactly the GNAT semantics. How about "pragma
Not_Referenced"? The semantics should be, in Tucker's words
"not mentioned" - not reading, no attributes and no semantic
effect at runtime.

If adding entries to this list would be deemed expensive to
implement,  I'd be happy to leave its effect limited to:
1) parameters
2) objects
3) subprograms
4) units in context clauses

I could possibly even live without 4) - the benefit to this
is going to >95% of the time with item 1).

Actually, I could even live with item 1) being the only
entity that this pragma dealt with - "pragma
Unused_Parameter" - it might even make it feasible to define
a set of rules that work! :-).

I have used this sort of rule in another language before
and it *was* used and did prove useful then.

****************************************************************

From: Nick Roberts
Sent: Tuesday, April 15, 2003  5:47 PM

----- Original Message -----
From: <martin.dowie@baesystems.com>


> As it is often said that a poor proposal is better than no proposal, I
> offer this effort.

I can only apologise myself for my manifest ineptitude at making (various)
proposals. I think the proposal Martin made would have to be elaborated upon
a little. I suspect a new section would need to be added to the RM regarding
warnings for 'abnormally used' entities. I think it would be advantageous
for such a section to be added, but I guess Randy would disagree.

> The one thing that struck me was when looking through the ARM, I couldn't
> see any other similar pragma - one that acts on objects and subprograms
> and, perhaps more importantly, deals with *warnings*, so I have left the
> heading number and placement to the ARG (should it be approved).

Similarly, I've not attempted any numbering related to the current RM.

I have changed the name of the pragma (from "Unreferenced", which GNAT
currently uses). I believe the disruption caused by this to the
implementation of GNAT would be minimal, and the disruption to GNAT users
would be none at all if GNAT were simply to retain implementation of the
pragma Unreferenced (as a synonym for Abnormal_Usage).

I have avoided extending the pragma to apply to library units mentioned in a
the context clause of a unit but never used inside the unit, because the
simpler solution to getting spurious warnings from doing this is to comment
out the (relevant part of the) context clause until it is needed.

What I present here is not complete. I thought perhaps it would be better to
post it as it is now, in the light of the fact that it may well be rejected
anyway :-( It should not be taken as a fait accomplis, but only a starting
point for much further refinement.


!standard L


!subject pragma Abnormal_Usage (was Unreferenced)


!summary

This AI proposes:

* a section is added to the RM giving guidance on warnings to be given for
abnormally used entities;

* a standard pragma is introduced, called Abnormal_Usage, which applies to
the declaration of a view (of an entity), and indicates that the view is
expected to be abnormally used.


!problem

During the sometimes lengthy process of the development of a software module
it is common for the usage of views (of entities) declared within the module
to be 'abnormal'. Abnormal usage, for example, might include a subprogram
parameter which is never read or updated in the body of the subprogram.

Compilers are likely to be programmed to give a warning about abnormal use,
because of the suspicion that the abnormal use indicates an inadvertant
error. Such warnings can be problematic in that they can occur in such
profusion as to obfuscate other, more important, warnings.


!proposal

A section is added to the RM explaining when a compiler should give a
warning about the abnormal usage of a view of an entity.

The new section describes a new pragma, "Abnormal_Usage", which allows the
programmer to indicate that an entity is expected to be abnormally used (for
the time being). Compilers will be expected to suppress any abnormal use
warning for any view which is so indicated, and to give a warning otherwise.

The form of the pragma Abnormal_Usage is as follows:

   pragma Abnormal_Usage ( view_name {, view_name} );

In addition, compilers will be expected to produce a warning for any view
indicated by this pragma but which is not, in fact, abnormally used (because
of the suspicion that the pragma itself has been aberrantly applied or not
deleted).


!wording

*** Insert section:

A.B Usage Warnings and Pragma Abnormal_Usage

An implementation shall provide a warning for every occurrence of a view of
an entity that is 'abnormally used' unless that view is 'marked for abnormal
use'. An implementation shall provide a warning for every occurrence of an
view that is not abnormally used and is marked for abnormal use.

A view is defined as abnormally used if it is not declared within the
visible part of a library package, and:

* it is not a library unit and there is no usage name of it within the scope
of its declaration;

* it is of an object which is not volatile, a loop parameter, or of a task
or protected type, and whose value could not possibly be read by any
execution of the program;

* it is of a variable object which is not volatile or of a task or protected
type and whose value could not possibly be updatde before being read by any
execution of the program;

* it is of an exception and there is no usage name of it in a raise
statement;

* it is of a callable entity and there is no usage name of it in a call;

* [others?]

A.B.C Pragma Abnormal_Usage

An occurrence of a pragma Abnormal_Usage identifies an entity which is to be
marked for abnormal use.

Syntax

   view_name ::= direct_view_name | subprogram_parameter_name

   direct_view_name ::= identifier

   subprogram_parameter_name ::= subprogram_name . parameter_name

   subprogram_name ::= identifier

   parameter_name ::= identifier

The form of a pragma Abnormal_Usage is as follows:

   pragma Abnormal_Usage ( view_name {, view_name} );

Name Resolution Rules

If the view name is a direct view name, it shall resolve to denote one or
more declarations in the same declarative region as the pragma. If the view
name is a subprogram parameter name, the subprogram name shall resolve to
denote one or more subprogram declarations in the same declarative region as
the pragma, and the parameter name shall resolve to denote one of the
parameters of each such subprogram declaration which has a parameter of that
name.

[Several other kinds of view name could be added. For example, components of
a record type declaration.]

Legality Rules

A pragma Abnormal_Usage is only allowed in a declarative region.

If a view name is a subprogram parameter name, it must denote at least one
subprogram parameter.
Static Semantics

A pragma Abnormal_Usage applies to the views which each view name applies
to. If a view name is a direct view name it applies to the view of each
declaration it denotes. If a view name is a subprogram parameter name, it
applies to the subprogram parameters it denotes.

Each view to which a pragma Abnormal_Usage applies is marked for abnormal
use.

Dynamic Semantics

Abnormal_Usage has no effect other than those described above.

Implementation Advice

If an implementation is not able to determine whether a view is abnormally
used, it should not consider the view to be abnormally used.

Implementation Permissions

An implementation is permitted to add further conditions under which a view
is considered to be abnormally used. All such further conditions must be
documented.

The form of the warnings produced by an implementation is not defined by
this standard.

*** Insert into Annex L replacing <A.B.C> with the appropriate cross
reference:

   pragma Abnormal_Usage ( view_name {, view_name} )]; -- <A.B.C>


!discussion

This AI attempts to standardize the Unreferenced pragma already supported by
various implementations.


!example

   procedure Log (I : Integer) is
   begin
      Put_Line ("Test stub for Log called");
   end Log;

   pragma Abnormal_Usage (Log.I);

****************************************************************

From: Tucker Taft
Sent: Wednesday, April 16, 2003 11:39 AM

I would suggest we avoid the term "referenced" completely,
if we are going to change the name.

How about:

   pragma Not_Used(local_name {, local_name});

and

   pragma Not_Read(local_name {, local_name});

The GNAT Unreferenced would be roughly equivalent to Not_Read,
I presume.  If we only want to standardize one, I would opt
for Not_Used since I think that is (a) easier to define
and (b) probably more useful.

****************************************************************

From: Orville E. Wheeler
Sent: Wednesday, April 16, 2003 11:49 AM

Tucker Taft is right.

It also has more intuitive appeal to me!

****************************************************************

From: Robert A. Duff
Sent: Wednesday, April 16, 2003  3:11 PM

I do not agree.  I think "never mentioned" and "never read" are roughly
the same potential bug, and I think only one pragma is in order.  I
think Not_Read is a superset of Not_Used, and both are "questionable",
deserving of warning, and deserving of a pragma to turn off the warning.
I don't much like the name "Unreferenced", but I think GNAT has
precedence -- the whole point of this discussion is to standardize
something already implemented by that compiler.  To redesign the
feature, for gratuitous reasons, defeats the purpose.

Unless the GNAT semantics are seriously broken, or ill defined, the ARG
should just take it or leave it as is -- not fiddle with it.

Look:

    X: Integer;
    Y: Integer := ...;
    Z: Integer;
    ...
    Z := ...;

You want me to use two different pragmas for X and Y and Z (if they are
not mentioned again)?!  Think from the user's point of view, here, not
the compiler writer's.

Maybe somebody from ACT can post RM-ish wording that exactly matches
what GNAT actually does.  The wording from GNAT's manual is not up to RM
standards (e.g. it talks about the "entity most recently declared",
which is of course nonsense: how is the compiler to know which
declaration I typed in most recently! -- the RM talks about "places" in
the source code).

Then we can judge whether the GNAT semantics makes sense.
If so, let's standardize it.  If not, let's forget the whole thing.

****************************************************************

From: Tucker Taft
Sent: Wednesday, April 16, 2003  3:55 PM

> I do not agree.  I think "never mentioned" and "never read" are roughly
> the same potential bug, and I think only one pragma is in order.  I
> think Not_Read is a superset of Not_Used, and both are "questionable",
> deserving of warning, and deserving of a pragma to turn off the warning.
> I don't much like the name "Unreferenced", but I think GNAT has
> precedence -- the whole point of this discussion is to standardize
> something already implemented by that compiler.  To redesign the
> feature, for gratuitous reasons, defeats the purpose.

The reasons for changing the name don't seem gratuitous, given
the number of messages this has generated.

I agree it would be ideal to standardize an existing pragma,
but it seems that it is sufficiently confusing that it would
be better to pick a new name.  As far as whether Not_Used or
Not_Read is more useful, I agree it is hard to decide which
is preferable.  As mentioned above, getting the definition
of "Not_Read" correct may be subtle, but I am willing to wait
until someone from ACT takes a shot at it.  On the other hand,
I believe Not_Used would get you at least 95% of the benefit
of Not_Read, and has a very simple definition (famous last words ;-).

> Unless the GNAT semantics are seriously broken, or ill defined, the ARG
> should just take it or leave it as is -- not fiddle with it.
>
> Look:
>
>     X: Integer;
>     Y: Integer := ...;
>     Z: Integer;
>     ...
>     Z := ...;
>
> You want me to use two different pragmas for X and Y and Z (if they are
> not mentioned again)?!  Think from the user's point of view, here, not
> the compiler writer's.

If you really want something to use as a "dummy" target of an
assignment, it seems simple enough to initialize it on declaration.
I just think it will look weird to see:

    Z: Integer;
    pragma Unreferenced(Z);
 begin

    Z := ...;

Such a use of the term "unreferenced" is counterintuitive to me.

****************************************************************

From: Randy Rbukardt
Sent: Wednesday, April 16, 2003  5:03 PM

> Unless the GNAT semantics are seriously broken, or ill defined, the ARG
> should just take it or leave it as is -- not fiddle with it.

I asked Robert Dewar (privately, since he's not on this list) about this
pragma and the discussion yesterday. I won't post his exact response (I
don't post private mail publicly) but here's my paraphrase of it:

1) He agreed with my feeling (posted yesterday) that the pragma Unreferenced
(which deals with warnings) is a poor candidate for standardization. (Well,
he said 'rubbish' :-).

2) He thinks that making programs illegal by the use of this pragma is
'wildly misguided'.

3) ACT does not want to have to change their implementation, which they
would need to do if we standardized something different than the current GNAT
implementation. See (1) and (2).

4) They choose the way Unreferenced work for good reasons (which he didn't
elaborate on), but he added that they're pragmatic reasons, as with all
warnings.

So, I think we need to change the name of this pragma (if we want to make
this something we can say something useful about in the RM). Otherwise, I
think we should drop the idea - if the designer of the pragma thinks its a
bad idea, why should we claim to know better??

****************************************************************

From: Jean-Pierre Rosen
Sent: Wednesday, April 16, 2003 12:18 PM

> If adding entries to this list would be deemed expensive to
> implement,  I'd be happy to leave its effect limited to:
> 1) parameters
> 2) objects
> 3) subprograms
> 4) units in context clauses
>
> I could possibly even live without 4) - the benefit to this
> is going to >95% of the time with item 1).

Definitely NOT!
Example: AWS.
A web page is actually a package, whose initialisation code registers
call-backs to the server. You must with these packages for them to be included
in the application, but they are not otherwise used (the specification may well
be empty).

Other example: packages that start tasks.

****************************************************************

From: Bernard Maudry
Sent: Thursday, April 17, 2003  3:51 AM

I really think that this is only needed for parameters so the pragma should be
named Unused_Parameter. If the others are unused, removing them or commenting
them out is the best solution.

For with clauses, the fact that the indicated entity is unused (like
Link_Options) is not to be warned unless the programmer explicitly asked
for such a warning.

****************************************************************

From: Robert A. Duff
Sent: Thursday, April 17, 2003  2:37 PM

A few days ago, I went through all the unused entities in a program of
about 100,000 lines of code.  There were about 500 cases.  About half
were with_clauses.  Of those, about 50 were correct (i.e. there was good
reason to with the thing and not refer to it).  The rest were simply
useless with_clauses -- harmless, except for cluttering the code,
and increasing compile time.

I didn't count the non-with_clause half carefully, but I guess about
half of those were parameters and half were local variables.  Almost all
were legitimate.  A couple of cases were actual bugs, something like
this:

    procedure P(A: T1; B, C, D, E, F: T2 := Default);

    ...

    procedure Q(B, C, D, E, F: T2 := Default) is
    begin
        P(A => Something,
          B => B, C => C, D => D, E => E); -- wrong!
    end Q;

where the intent was for Q to be a wrapper for P, filling in the A
parameter, and passing all the rest along unchanged.  But the F
parameter is missing above, and therefore generated the "unused entity"
warning.

As to the legitimate cases, there were a few common reasons.  A common
technique is to declare an object of a Limited_Controlled type, purely
for the purpose of running the Initialize and Finalize routines.
There were also examples like "Ignore: constant T := F(...);"
where the purpose is to call F for side effects and ignore the result.
And there were cases where a formal parameter was required, because
the procedure was overriding another procedure, or was being passed to a
generic, so its profile had to match some other thing, but in this
particular case, the procedure didn't want to look at its parameter.

****************************************************************

From: Robert I. Eachus
Sent: Thursday, April 17, 2003  5:53 PM

>I really think that this is only needed for parameters so the pragma
>should be named Unused_Parameter.

I totally disagree.  First unused parameters are one useful case, but
there are several others of equal or greater weight. Second, even if it
were limited to parameters, naming the pragma Unused_Parameter is an
extreme case of lily guilding, since the name of the unused entity or
entities will immediately follow.

Having a pragma with a name like Not_Used or maybe even Unused would
allow me to eliminate a number of non-meaningful junk names (usually
Junk ;-) from my code.

Robert A Duff wrote:

> A few days ago, I went through all the unused entities in a program of
> about 100,000 lines of code.  There were about 500 cases.  About half
> were with_clauses.  Of those, about 50 were correct (i.e. there was good
> reason to with the thing and not refer to it).  The rest were simply
> useless with_clauses -- harmless, except for cluttering the code,
> and increasing compile time.

The with clause case is a major argument for a standard pragma.  I know
that the meaning is more like "not used here, but my children need it
here for elaboration sequence reasons."  But that is a little too long
for even an Ada pragma name.

But the real need for the pragma in the with clause case is that it
allows a programmer to document a decision in a meaningful way.  By
having both the with clause and the pragma, he says that this isn't
junk, there is a reason it is located here.

Now a maintenance programmer coming along later won't introduce a bug by
moving the with clause to what looks to him as a more appropriate
location.  (Usually from package specification to package body.)

> I didn't count the non-with_clause half carefully, but I guess about
> half of those were parameters and half were local variables.  Almost all
> were legitimate.  A couple of cases were actual bugs, something like
> this...

Exactly.  Five hundred warning messages are either never going to be
checked, or checked only once.  Cut that to three, and even if only two
are errors, the errors will be found and fixed.

> As to the legitimate cases, there were a few common reasons.  A common
> technique is to declare an object of a Limited_Controlled type, purely
> for the purpose of running the Initialize and Finalize routines.
> There were also examples like "Ignore: constant T := F(...);"
> where the purpose is to call F for side effects and ignore the result.
> And there were cases where a formal parameter was required, because
> the procedure was overriding another procedure, or was being passed to a
> generic, so its profile had to match some other thing, but in this
> particular case, the procedure didn't want to look at its parameter.

Yep, I run into the parameter formal matching case fairly often.  But
there is one case I ran into where NOT using the pragma would have saved
a lot of trouble.

The issue involved an AVL tree where normally look-ups were done using
one key.  But there were occasions where every entry had to be examined
based on a secondary key--eliminating expired entries based on a date.
I won't show the gory code here.  {Lots of text eliminated by author
here.  Send e-mail if you really must know.}

So what was the problem?  A compiler warning that Current_Key might
never be assigned a value.  Since it was only set or read in nested
subprograms, the warning was true, but gratuitous.  Kludges to eliminate
that warning got us into trouble on too many occasions.  The final
solution was a comment:

   Current_Key: Name; -- Do not touch.  This especially means me. -- RIE

****************************************************************

From: Martin Dowie
Sent: Monday, April 21, 2003  4:24 AM

Ok - here is a more limited version using the name 'Not_Used'. This
proposal is currently limited to parameters. The only other area that
I can see being of any real benefit would be usused context clauses.
I may come back with an update that includes a rule for that, time
permitting.

I've avoided using 'Unused_Parameter' so that, as rule for other
language features become available they can be added.


============================================================================
!standard L

!subject pragma Not_Used

!summary

A standard "Not_Used" pragma is proposed which takes one or more,
defining_identifier as parameters. This pragma indicates that each of the
defining_identifier is not expected to be referenced within the current
scope.

!problem

It is common for test stub subprograms and for callbacks not to use all the
parameters passed to them. This pragma allows the programmer to specifically
indicate that they do not expect an entity to be referenced within the
subprogram.

!proposal

The form of the pragma Not_Used is as follows:

    pragma Not_Used(defining_identifier {,defining_identifier});

  A pragma Not_Used is only allowed in a declarative_part. The
  defining_identifier of a pragma Not_Used shall resolve to a formal parameter.

!wording

Insert section:

A.B.C Pragma Not_Used

An occurrence of a pragma Not_Used identifies a set of defining_identifiers
which are declared but intentionally unused. The purpose of such a pragma is
to help identify formal parameters that are declared and not intended to be
used but are erroneously referenced.

Syntax

The form of a pragma Not_Used is as follows:

pragma Not_Used(defining_identifier {,defining_identifier});

Legality Rules

4 A pragma Not_Used is only allowed immediately within the declarative_part of
a
subprogram_body, prior to any declarative_item.

5 Each defining_identifier shall statically denote a formal parmeter.

6 It is illegal to reference a defining_identifier denoted by a pragma
Not_Used.

Static Semantics

7 A pragma Not_Used indicates to an implementation that the defining_identifier
is deliberately not used within the current scope.

Dynamic Semantics

8 Execution of a pragma Not_Used has no effect.


Insert into Annex L replacing <> with the appropriate cross reference:

    pragma Not_Used(defining_identifier {,defining_identifier}); -- <A.B.C>

!discussion

This AI attempts to standardize a Not_Used pragma that provides some of
the benefits of an existing implemenation defined pragma.

To avoid confusing with the existing implementation, the pragma name has
been changed.

!example

    procedure Log (I : Integer) is
       pragma Not_Used (I);  -- Legal
    begin
       Put_Line ("Test stub for Log called");
    end Log;

    procedure Log (I : Float) is
       V : Integer := Integer (I);
       pragma Not_Used (I); -- Illegal, pragma comes too late, "I" already used
    begin
       Put_Line ("Test stub for Log called");
    end Log;

****************************************************************

From: Robert A. Duff
Sent: Monday, April 21, 2003  1:08 PM

Well, I still say GNAT got it right (as far as I can tell -- I haven't
seen a precise description of what GNAT does).  The only complaint about
the GNAT solution that I agree with is a mildly poor choice of name.
But it's not *that* bad; it's certainly not worth "fixing" when many
users already have it in their code.  And, as far as I can tell, the
semantics of all the proposed alternatives is inferior to that of GNAT's
pragma.

****************************************************************

From: Martin Dowie
Sent: Monday, April 21, 2003  4:03 PM

The only problem I have with the GNAT name is that it isn't obvious that
you can actually referenced something marked as 'Unreferenced' - I think
it came as a surprise to a few people on the list, judging by the subsequent
comments! (As far as I can see, the user guide in the public version doesn't
contain the 'full definition' that was quoted a few days ago).

I'm sure ACT had good reason for making it so, but it seems to run counter
to 'the principle of least surprises'.

I've got another proposal that adds rules to allow with_clause checking, if
it is felt that would be of benefit. I'm still not convinced about the need
to cover variables/constants/subprograms/entries, but if someone wants to
write up those rules, feel free!

****************************************************************

From: Stephen Leake
Sent: Tuesday, April 22, 2003  9:55 AM

> (As far as I can see, the user guide in the public version doesn't
> contain the 'full definition' that was quoted a few days ago).

Here's the complete text from the GNAT 3.16a reference manual (GNAT
3.16a is a current ACT pre-release):

---------------
Syntax:

     pragma Unreferenced (local_Name {, local_Name});

This pragma signals that the entities whose names are listed are
deliberately not referenced. This suppresses warnings about the
entities being unreferenced, and in addition a warning will be
generated if one of these entities is in fact referenced.

   This is particularly useful for clearly signaling that a particular
parameter is not referenced in some particular subprogram implementation
and that this is deliberate. It can also be useful in the case of
objects declared only for their initialization or finalization side
effects.

   If `local_Name' identifies more than one matching homonym in the
current scope, then the entity most recently declared is the one to
which the pragma applies.

   The left hand side of an assignment does not count as a reference
for the purpose of this pragma. Thus it is fine to assign to an entity
for which pragma Unreferenced is given.

--------------

The last paragraph (allowing assignment) did not appear in the GNAT
3.15p reference manual.

The latest ACT pre-release is GNAT 5.00a; it has the same text as 3.16a

> I'm sure ACT had good reason for making it so, but it seems to run counter
> to 'the principle of least surprises'.

I agree. I can only assume that some customer needed the "allow
assignment" case, and ACT felt is was a reasonable thing to do, so
they added it in GNAT 3.16a. Now that I know it is there, I will
probably use it as well, for example for ignoring irrelevant results
from Win32 API functions.

> I've got another proposal that adds rules to allow with_clause
> checking, if it is felt that would be of benefit. I'm still not
> convinced about the need to cover
> variables/constants/subprograms/entries, but if someone wants to
> write up those rules, feel free!

I think I can see why Robert Dewar says it's not worth trying to
standardize this. In some ways, it is highly specific to the warnings
that GNAT gives. If other compilers don't give similar warnings, this
pragma is useless to them.

I suppose an annex on recommended warnings might be a way to go, but I
doubt it is worth it.

Perhaps this is a good candidate for a "secondary standard", rather
than trying to put it in the main Ada standard.

****************************************************************

From: Martin Dowie
Sent: Wednesday, April 23, 2003  2:29 AM

> I think I can see why Robert Dewar says it's not worth trying to
> standardize this. In some ways, it is highly specific to the warnings
> that GNAT gives. If other compilers don't give similar warnings, this
> pragma is useless to them.

I can see why it's not worth trying to standardize the current GNAT
pragma (including name) but I think a simpler semantics and differently
named pragma is worth the effort.

From what Tucker has said this would be an easy change for compiler
writers and the simply semantics doesn't have the problem for Janus
that Randy described.

As for other compilers that don't currently give a warning, the mean
implementation would provide them an ideal chance to include a fairly
useful warning! :-)

****************************************************************

Questions? Ask the ACAA Technical Agent