Version 1.2 of ais/ai-00274.txt

Unformatted version of ais/ai-00274.txt version 1.2
Other versions for file ais/ai-00274.txt

!standard 13.5.1(2)          01-09-19 AI95-00274/00
!class amendment 01-09-19
!status work item 01-09-19
!status received 01-09-11
!priority Low
!difficulty Easy
!subject Requiring complete record representation clauses
!summary
A pragma is added to force all record components to be given in a record representation clause.
!problem
Record representation clauses (13.5.1) allow the locations for the components of a record to be specified, but there is no way to ensure that the location for each and every field is specified. If you do not specify the location for a component then the compiler can put it anywhere. This is often not what is wanted, as many times when rep clause is used the location of all fields will need to be specified.
For example, assume you have
type R is record field1 : typea; field2 : typeb; field3 : typec; end record;
for R use record
field1 at 0 range ...; field3 at 3 range ...;
end record;
This is probably an error, since the location for field2 has been left out. In this example it is blatantly obvious, however in real world code (for example the layout of bus messages) there can be many fields and it is easy to leave one out. This can lead to hard to find errors.
!proposal
(Add a pragma, semantics TBD.)
!wording
!example
!discussion
!appendix

!topic Complete Record Representation Clauses
!reference RM95-13.5.1
!from Chris Miller 01-09-11
!keywords record representation clause
!discussion

Here is a quick suggestion for Ada 0X. I have no idea if it has been
suggested before.

Record representation clauses (LRM13.5.1) allow the locations for the
components of a record to be specified, but there is no way to ensure that
the location for each and every field is specified. If you do not specify
the location for a component then the compiler can put it anywhere. This is
generally not what is wanted, if a rep clause is used then typically the
location of all fields will need to be specified.

Assume you have

type R is record
  field1 : typea;
  field2 : typeb;
  field3 : typec;
end record;

for R use record
  field1 at 0 range ...;
  field3 at 3 range ...;
end record;

This is probably an error, since the location for field2 has been left out.
In this example it is blatantly obvious, however in real world code (for
example the layout of bus messages) there can be many fields and it is easy
to leave one out. This can lead to hard to find errors.

The addition could be to allow an optional reserved work "all" in the record
rep clause, in this case it would be a compile time error if the component
clauses for all fields were not specified.

So you would get

for R use all record -- new optional keyword "all"
  field1 at 0 range ...;
  field2 at 3 range ...;
  field3 at 7 range ...;
end record;

This would be trivial to implement, and 100% upward compatible with current
code. May also wish to have a pragma that specifies that all record rep
clauses in its scope are complete. This could be either a new pragma or part
of pragma Restrictions, in the Safety & Security Annex. It may even be a
configuration pragma (?).

The justification and use for this feature is that it it would help reduce
errors. I had a case where there were many fields in a record describing a
1553B bus message. One component clause in the record rep clause was missing,
the compiler then put it in a different location to that desired and this led
to problems. The error was eventually found, but it took some time. It is
especially difficult to locate such mistakes when there are a lot of records
with rep clauses and / or there are a lot of fields in each record.

This feature would have prevented this error.

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

From: Marc C. Criley
Date: Friday, September 14, 2001  6:23 AM

I've had experience with the situation that this suggested feature would
have helped prevent.

Our application had a large data record communicated to non-Ada
applications, so it was essential that there be a rigid data layout, ensured
by using a representation specification.  Occasionally a new field would be
added, and the need for a corresponding rep spec would be overlooked (the
project environment was very dynamic and high pressure).  Depending on where
the compiler chose to place this new component, the problem could be found
immediately, or not until later changes caused a ripple effect that
relocated that record field to somewhere where it would no longer work.

Also, different compilers can take quite different approaches to placing
those components that have no specifications (as is permitted by the
standard).  Alsys Ada 83 and GNAT did just that, and so some of the record
layouts resulting from porting software, containing records with "partial"
rep specs, from one compiler to the other caused a great deal of confusion
at the time.

Having the "all" keyword used in the context suggested by Chris, or a
comparable pragma, would have prevented problems we experienced, or at least
made developers more aware of the freedom granted compilers when placing
record components having no rep spec.

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

From: Robert Dewar
Date: Tuesday, September 18, 2001  3:10 AM

I would think a pragma much more appropriate than this rather odd use of the
ALL keyword.

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

From: Robert Dewar
Date: Tuesday, September 18, 2001  3:10 AM

The other advantage of a pragma is that it can be implemented immediately,
and is not a language extension.

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

From: Pascal Leroy
Date: Wednesday, September 19, 2001  8:01 AM

I agree that a pragma is preferable, and that there is no good reason to come
up with new syntax for such a minor change.

I see some difficulties in defining the semantics of that pragma in RM terms,
though.  We'd have to decide what to do with implicit components, components
with a dynamic size, etc.  I am unsure whether it's worth the effort.

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

From: Marc C. Criley
Date: Wednesday, September 19, 2001  6:57 AM

So what are candidate names and constructions for such a pragma?

E.g.:

pragma Record_Representation_Specification_Policy([record-type-name],
[policy]);

[record-type-name] is the name of a record type to which a representation
specification may be applied.

[policy] is Prohibited, Unspecified, or Complete.

"Prohibited" forbids applying a representation specification to the record
type.  This may be appropriate when the record type is used for
straightforward interfacing to other languages--where the use of pragma
Convention is preferred--and would prevent programmers from automatically
assuming rep specs need to be provided for structures being passed to other
languages--a trait probably more common among Ada 83 programmers.  (An
alternative to "Prohibited" might be "Convention", to indicate that a pragma
Convention must be applied to the type.)

"Unspecified" is provided for completeness, and indicates that the record
may have any or no representation specification, i.e., the current
situation.

"Full" requires every record field be covered with a representation
specification.


Other issues:

How do tags and compiler-generated record fields interact with this pragma?

Perhaps [record-type-name] could instead be [entity-name], where it could
specify the name of a compilation unit and the policy then applied to every
record type definition in that compilation unit.

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

From: Marc C. Criley
Date: Wednesday, September 19, 2001  7:46 AM

Pascal Leroy wrote:

> I see some difficulties in defining the semantics of that pragma in RM
> terms, though.  We'd have to decide what to do with implicit components,
> components with a dynamic size, etc.  I am unsure whether it's worth
> the effort.

I do understand that there are difficulties, but I and others can personally
attest that the inability to enforce comprehensive record representation
specification directly led to development and porting difficulties, which
sometimes did not manifest themselves until long after software
modifications occurred.

As a specific example of the latter:  We used a variant record to pass
display updates from an application's "core" process to its GUI process (and
different variants required significantly varying amounts of space).  GNAT's
approach to placing record components having no rep spec is to put them
"after" the space allocated for components that do have rep specs.  In the
primary configuration of the system, both the core and GUI processes were
implemented in Ada, so everything functioned correctly.  It was later
discovered, when integrating into the system a non-Ada GUI process, that
certain updates that should require only about two dozen bytes to convey
were actually transmitting over 12 KBytes across the network every time they
occurred!  This obviously impacts network loading and required development
time to identify the root cause of the problem amongst the new process, the
interface, and the core process.

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

From: Robert Dewar
Date: Wednesday, September 19, 2001  8:57 AM

I am inclined to think that a language extension here is overkill. Seems to me
that a simple ASIS tool would be much more appropriate.

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

From: Pascal Leroy
Date: Wednesday, September 19, 2001  9:18 AM

> I am inclined to think that a language extension here is overkill. Seems to
> me that a simple ASIS tool would be much more appropriate.

I agree with this assessment.

As a matter of fact, our Ada editor has a command to build or complete
representation clauses.  We initially developed it to make it easy to add
confirming representation clauses, so as to avoid the situation where a change
in the way we lay out types wreaks havoc in applications.  But it also turned
out to be useful in the situation described here, because our compiler puts the
components that don't have representation clauses after all the rest (I am
hearing that GNAT does the same).

The output is very much implementation-specific, because it produces component
clauses for implicit components like tag, size, etc. (using the attribute
notation of 13.5.1(9)).  That's why I am anticipating difficulties in
formulating this capability in language terms.

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

From: Randy Brukardt
Date: Wednesday, September 19, 2001  10:30 PM

> I am inclined to think that a language extension here is overkill. Seems
> to me that a simple ASIS tool would be much more appropriate.

That might be true, but of course something added to the language would be
more generally available. After all, I don't think anywhere near all of the
compilers support ASIS.

The better question is whether this feature is important enough to get into
what we hope will be a fairly small set of enhancements. I'm not sure it
meets that criteria, even if it is useful.

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

From: Randy Brukardt
Date: Wednesday, September 19, 2001  11:16 PM

Does ASIS know about implicit components? Given the scenarios discussed, I
would think that they need to be included in the check. The compiler obviously
knows when it is going to generate an implicit component, but could an ASIS
tool?

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

From: Randy Brukardt
Date: Wednesday, September 19, 2001  11:11 PM

> I see some difficulties in defining the semantics of that pragma in RM terms,
> though.  We'd have to decide what to do with implicit components, components
> with a dynamic size, etc.  I am unsure whether it's worth the effort.

Well, given the sort of cases that seem to be an issue here, I would suggest
that the program is illegal if the pragma applies and ALL components are not
specified. That means that if there are any dynamic components or implicit
components that can't be specified, the pragma can't be used. Tough. (Of
course, that does mean that there probably isn't much value to a configuration
pragma for this, because it probably would make most RTSes illegal.)

If this is going to be done at all, it has to be very simple.

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

From: Robert Dewar
Date: Thursday, September 20, 2001  4:43 AM

By the way, in practice, a good defence against this in the current language
is to specify the size. If you have forgotten a component in the layout, the
size you specify will be incorrect, and will be rejected. This is not 100%
bullet proof, but works well in practice.

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

From: Marc C. Criley
Date: Thursday, September 20, 2001  6:02 AM

And unfortunately as well, the expertise required to write a "simple ASIS
tool" is not at all common.  Indeed, the mere fact that something called
ASIS _exists_, much less its purpose, is unknown to most journeyman Ada
programmers.

Given that lack of capability, there's little likelihood of addressing what
has been a very real issue unless compiler vendors themselves provide such a
tool.

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

From: Robert Dewar
Date: Thursday, September 20, 2001  7:10 AM

It is a whole lot easier to provide such a tool than to go modifying the
compiler.

I would say that since this can be done with a pragma, let's see if any
compiler vendor is interested in implementing such a pragma. If there is
insufficient demand from any customers to make such an implementation
appropriate, then it is hardly appropriate for the ARG to go mandating
a change from everyone.

So I think Marc in the first place should try to persuade his vendor to
implement such a pragma.

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

From: Pascal Leroy
Date: Thursday, September 20, 2001  7:06 AM

> Does ASIS know about implicit components? Given the scenarios discussed, I
> would think that they need to be included in the check. The compiler
> obviously knows when it is going to generate an implicit component, but
> could an ASIS tool?

If they are nameable by attributes, then yes,
Asis.Data_Decomposition.Record_Components returns them.

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

From: Randy Brukardt
Date: Thursday, September 20, 2001  9:02 PM

And if they are not nameable? Certainly the RM makes no requirement that they
are named, only that if they are named, they will be named as attributes.

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

From: Robert Duff
Date: Thursday, September 20, 2001  12:30 PM

> Does ASIS know about implicit components?

I think the implicit components issue is a bit off a red herring.
The cases where this matters usually won't have implicit components.

This is the usual language-lawyer thing: Programmer asks, "Why can't I
say `2 + 2' in Ada?"  Language lawyer: "Well, you see, if a program had
a generic formal tasking discriminatated aggregate, then this would
introduce an obscure blah blah blah."  Programmer: "But I don't have any
generic tasking whatevers -- I just want to add 2 plus 2."

For implicit components, any well-defined rule is good enough, such as
the one you suggest:

>...Given the scenarios discussed, I
> would think that they need to be included in the check. The compiler
> obviously knows when it is going to generate an implicit component, but
> could an ASIS tool?

BTW, I agree with others who doubt the importance of spending a lot of
ARG time on this.  I agree with Robert Dewar, who suggested first trying
to get some implementer to implement a pragma.  Or an ASIS tool.

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

From: Randy Brukardt
Date: Thursday, September 20, 2001  9:21 PM

> I think the implicit components issue is a bit off a red herring.
> The cases where this matters usually won't have implicit components.
> ...
>
> For implicit components, any well-defined rule is good enough, such as
> the one you suggest:

I certainly agree that the user won't be using types where they expect implicit
components. But if an evil compiler inserts one when the programmer doesn't
expect it, it certainly would be valuable for the compiler to complain. So I
don't think that ANY rule is good enough. It is precisely this reason that an
ASIS tool won't do the job -- it doesn't necessarily know about implicit
components.

> ... I agree with Robert Dewar, who suggested first trying
> to get some implementer to implement a pragma.

Well, I can implement such a pragma in a hour or so. Finding a symbol table bit
to use would be the hardest part. The check is trivial: if the "complete" bit
is set, the freezing code that locates unspecified components pumps out an
error message. So I don't think that should be much of a criteria. (If Marc
will buy a Personal Edition compiler, I'll do it for him. :-)

The big problem with this one is that it is one of those issues that everyone
understands, so the ARG will spend 5 times as long on it as on something hard
and important. :-)

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

From: Robert Dewar
Date: Thursday, September 20, 2001  10:28 PM

The fact that something takes 1 hour to implement is not very relevant. If
we implemented everything that satisfied this criterion, then we would have
a forest of junk, and no time to do anything else.

We would only implement this if we had a customer who could successfully
show that this was an important change with no effective alternative
aproach (as I said earlier, I think that in practice specifying a size
works just fine).

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

From: Randy Brukardt
Date: Thursday, September 20, 2001  11:02 PM

> The fact that something takes 1 hour to implement is not very relevant. If
> we implemented everything that satisfied this criterion, then we would have
> a forest of junk, and no time to do anything else.

Well, most compilers do have a number of "features" that meet the "forest of
junk" criteria.

> We would only implement this if we had a customer who could successfully
> show that this was an important change with no effective alternative
> aproach (as I said earlier, I think that in practice specifying a size
> works just fine).

I think it would be best to simply say that you think that this proposal has
insufficient value. Trying to lean on implementation concerns and the always
useful "no effective alternative" just confuses matters. (That was my point
above, although it may have been a bit obscure.)

While this proposal has no technical or implementation problems, it doesn't
seem like something that would get out of the "nice to have" category. And as
we know, everything in that category was omitted from Ada 95. Why would anyone
expect Ada 0y to be different in this respect?

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

From: Robert Dewar
Date: Thursday, September 20, 2001  10:28 PM

<<Well, most compilers do have a number of "features" that meet the "forest of
junk" criteria.>>

I don't think that's true, certainly there is nothing in GNAT that has not
met the criterion of being needed and useful by one or more of our customers,
or is a major development that we have carefully designed.

<<I think it would be best to simply say that you think that this proposal has
insufficient value. Trying to lean on implementation concerns and the always
useful "no effective alternative" just confuses matters. (That was my point
above, although it may have been a bit obscure.)>>

You miss my point completely. The proposal has definitely sufficient value
IF it is really the case that at least one or more serious users of Ada
would find it significantly useful. If one of our customers is in this
category, and is willing to fund the development, then it would have
sufficient value.

My point is that the ARG should not be in the business of mandating new
features merely because someone thinks something is nice to have.

In the setting of a commercial vendor supplying customers, you have an
immediate criterion of whether serious interest and need exists.

That's why I suggested that a first step is a trial implementation in
one compiler. If no one can justify this, then I see no reason to move
further. After all many of the features we *have* added like C_Pass_By_Copy
have exactly that history.

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

From: Randy Brukardt
Date: Friday, September 21, 2001  12:59 PM

> <<Well, most compilers do have a number of "features" that
> meet the "forest of junk" criteria.>>
>
> I don't think that's true, certainly there is nothing in GNAT that has not
> met the criterion of being needed and useful by one or more of our customers,
> or is a major development that we have carefully designed.

Features added specifically for a single customer, or to provide a very
specific need, are almost always in the "junk" category. Implementers need to
add these things to get things done and keep their customers happy, but that
doesn't magically turn them into well-designed language features. Every compiler
I've looked at has plenty of them, GNAT included.

> You miss my point completely. The proposal has definitely sufficient value
> IF it is really the case that at least one or more serious users of Ada
> would find it significantly useful. If one of our customers is in this
> category, and is willing to fund the development, then it would have
> sufficient value.
>
> My point is that the ARG should not be in the business of mandating new
> features merely because someone thinks something is nice to have.

And I've been making the same point. I just don't think it matters whether or
not a single customer comes to ACT or Rational or whomever to add it. That is
exactly how we get the "forest of junk" language design. My point in offering
to add it for $195 is to prove that that criteria is too easily corrupted.

In this particular case, I don't see the feature getting out of the "nice to
have" category even if every ACT customer demands it is added tomorrow --
precisely because ACT (and everyone else) could support it if asked without
any help from the ARG. There are a lot a features in GNAT (presumably added
because of customer demand) that the ARG has no interest in standardizing.

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

From: Robert Dewar
Date: Friday, September 21, 2001  1:15 PM

<<Features added specifically for a single customer, or to provide a very
specific need, are almost always in the "junk" category. Implementers need
to add these things to get things and keep their customers happy, but that
doesn't magically turn them into well-designed language features. Every
compiler I've looked at has plenty of them, GNAT included.>>

You are missing my point because your definition of junk is different
from mine.

My point, I will not use the word junk, is that an extra feature like the
one proposed cannot possibly be stuffed into the language on the basis
simply of one person saying this would be nice to have.

Either lots and lots of people (a real consensus) has to agree that this
is *so* nice-to-have that it should be put in even if there is no
demonstrated need.

Or need must be demonstrated, and for me a minimal demonstration of such
need is that at least one vendor finds enough need to implement.


As for features in GNAT, anyone can say anything is junk, but there are no
features in GNAT that do not meet the above criteria. In particular, you
may not like a particular feature in GNAT, but you can be sure that it is
there either because there was a substantial need (and for us substantial
need is more than just one customer being willing to buy one copy of the
compiler, which Randy said was his (much lower)_ threshhold). For example,
the DEC pragmas are considered by many to be junk, but there is of course
a critical need in dealing with legacy DEC Ada code, and that is a real
need that comes from multiple customers.

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


Questions? Ask the ACAA Technical Agent