A few thought regarding Cray's "Variable Length Array Proposal"

Tom MacDonald uunet!tamarack.cray.com!tam
Mon Feb 8 08:21:30 PST 1993


> This is my response to Tom MacDonald's response to my response to his
> VLA proposal.
> 
> I'll try to be brief.
> 
>   > 		void foobar (int n)
>   > 		{
>   > 			static int (*ap) [n];
>   > 		}
>   > 
>
> [[ ... lots of comments on the above example deleted ...]]
>
> It matters to implementors.  You want to strike that perfect balance
> between ease of implementation and power for the users.  In this case,
> I believe that the rules which the implementors have to make their
> compilers enforce will be simpler to implement if you allow the above
> example.

I really have no problem with including static pointers to VLAs.
to me it's a minor point.  I will include your comments in my next
presentation before the nceg committee and we'll see what they say.
I'd feel a lot better if I someone could think of a good example
where this is useful.  I still think it raises issues with "what does
static mean?" if we allow these constructs.  But, in the end, this
is not a major issue.

>   > >      ...Is  this  fundamental change  to  C's  lexical  ordering
>   > >      within  a  prototype acceptable?
>   > 
>   > No way!  It creates a horrendous amount of problems (some of which are
>   > described in the proposal itself) and does so for little (if any) *real*
>   > additional functionality.  TAKE THIS OUT!
>   
>   A large part of the rationale is dedicated to this very subject.
>   My belief is that, if thiss change to the lexical ordering is taken
>   out, then the entire proposal should be abandoned.
> 
> The rest of the proposal is admirable, and I see no reason to believe
> that it would not continue to be so, even in the absence of this
> unfortunate breach of C's existing lexical scoping rules (which
> generally go a long way towards permitting simple-minded one-pass
> compilation).
> 
> [[... stuff deleted about lexical ordering issue ...]]

I think we've managed to sum up both sides of the issue here.  In
general I find your average numeric and scientific programmer joe
on the street likes being able to put parameters in any order, and
your average stay up all night compiler writer says, "it's too much work."
I've taken a stand and I'll see how it comes out.


>   > >  ... If the object is variably qualified...
>   >                         ^^^^^^^^^^^^^^^^^^
>   > PLEASE PLEASE use a different term (e.g. "variable sized").  The term
>   > "qualified" already has an established (and very different) meaning
>   > with respect to ANSI/ISO C programs.
>   
>   How about variably modified?...
> 
> Anything will do... as long as you don't try to overload the meaning of
> "qualified".

Sounds good.


>   > >  ... and the block is
>   > >  entered by a jump to a labeled statement, then the  behavior
>   > >  is  undefined.
>   >        ^^^^^^^^^
>   > 
>   > Humm... Later on you say that jumping into a block past a declarative
>   > statement which requires the elaboration of a variable-length array type
>   > specification is simply illegal, and that a compile-time diagnostic is
>   > required!  So which is it?  Compile-time diagnostic or undefined behavior
>   > at run-time?
>   
>   Good point.  How aobut undefined behavior.  It's similar to bypassing
>   an initializer of an automatic object and the referencing the object.
>   I'll recommend that the constraint be removed...
> 
> Yikes!  That is exactly the *opposite* of what I was hoping for!  I think
> it is a good idea to *require* a diagnostic for attempts to jump into
> a block in such a way that you *avoid* elaborating declarations which
> involve VLA types.
> 
> Note that C++ already has similar rules.  In C++ you may not jump into a
> block if doing so will cause you to miss the elaboration of declarations
> which include initializations.
> 
> (I never liked those nasty old goto's anyway, so as far as I'm concerned,
> the more we clamp down on the most ill-structured uses of them, the better.)

Someone may complain that a required diagnostic is too hard to implement :^).

Actaully, the proposal stands the way it currently is because section
3.1.2.4 Storage Duration of Objects doesn't have a constraint section.
If we make this an error, the bypassing an initializer ought to be
an error.  If the re are good reasons for requiring a diagnostic in
this case, then those reasons apply to bypassing initializers also.
Both issues should be tackled at the same time.


>   > The rationale for this `[*]' notation is not provided (as far as I could
>   > see).  Why is it needed?  What does it do for us?  Can you get rid of it
>   > if you get rid of the weird exception to the normal lexical scoping rules
>   > for formal parameter names?
>   
>   I'll add some more rationale.  Getting rid of the exception to the lexical
>   scoping rules doesn't eliminate the need for the *.
> 
> I think it does.  (There goes another whole big batch of unnecessary
> complexity!)
> 
>   Consider the following prototype:
>   
>   	void f(int, int[*][*]);
>   
>   currently names are not required if there is no actual definition
>   of the function.  Without the `*' a name would be required.
> 
> And what would be wrong with that???  Is there some reason that:
> 
> 	void f(int n, int[n][n]);
> 
> ... would be "bad"?

Actually, yes, this can be bad.  In a large development project,
someone can introduce:

	#define n 10

which all of a sudden breaks your prototype.  If no names are
present then it's a lot harder to introduce names that conflict.
Personally, I never use names in prototypes, only in definitions.


>   > >  7.6.2.1 (4.6.2.1) The longjmp function
>   > >  
>   > >  Description
>   > >  
>   > >       If a longjmp function invocation causes the termination
>   > >  of  a  function  or  block  in  which  variable length array
>   > >  objects are still allocated, then the behavior is undefined.
>   >                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>   > 
>   > No good.  The behaviour *must* be defined.  Otherwise you have invented
>   > a highly crippled VLA feature.
>   
>   Really, it could be defined.  However, in many implementations this
>   could mean storage is lost.  This is just trying to acknowledge
>   that issue.  If a VLA is allocated on the heap...
>                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> ... then that would be a poor implementation.  Why would anyone want to
> implement this VLA feature in such a way that `auto' VLA objects get
> allocated out in the heap?  That would be a rotten way to do it, and it
> would make longjmp unreliable (as you have noted).

Actually, the CRI implementation allocates VLAs on the heap sometimes.
Our stack implementation is not contiguous.  I can't go into
all the details, but when you enter a parallel region, each task
gets its own stack, so the stack implementation allows a tree-like
structure.  Because of this, if there is not enough room in the
current stack segment, it is faster to put the VLAs on the heap.
This is true for both our Fortran and C implementations.  There are
good performance reasons for why we do this.

Thanks again for your comments.  I now have lots to do in my free time.

Tom MacDonald
tamacray.com
uunet!cray!tam



More information about the Numeric-interest mailing list