JTC1/SC22/WG14
N683
WG14/N683 (J11/97-046) WG14/N683 (J11/97-046)
Final Edits for incorporating VLAs into C9X
Tom MacDonald
tam@cray.com
655F Lone Oak Road
Eagan MN 55121
USA
08-May-1997
The following edits are against version C9XD9-pre3.
Quoted text (e.g., "sizeof") implies bold-courier font.
%%
%% Change #1
%%
6.1.2.4 Storage duration of objects
[#3] An object whose identifier is declared with no linkage
and without the storage-class specifier static has automatic
storage duration. Storage is guaranteed to be reserved for
a new instance of such an object on each normal entry into
the block with which it is associated
End the sentence in C9XD9-pre3 here, and replace its final clause:
, or on a jump from
outside the block to a labeled statement in the block or in
an enclosed block.
With:
. If the block with
which the object is associated is entered by a jump from
outside the block to a labeled statement in the block or in
an enclosed block, then storage is guaranteed to be reserved
provided the object does not have a variable length array
type. If the object is variably modified and the block is
entered by a jump to a labeled statement, then the behavior
is undefined.
End of change.
%%
%% Change #2
%%
Add the following forward references to 6.1.2.4
variably modified (6.5.4), variable length array (6.5.4.2).
End of change.
%%
%% Change #3
%%
6.1.2.6 Compatible type and composite type
[#3] A composite type can be constructed from two types that
are compatible; it is a type that is compatible with both of
the two types and satisfies the following conditions:
Replace the following words in C9XD9-pre3:
- If one type is an array of known size, the composite
type is an array of that size.
With:
- If one type is an array of known constant size, the
composite type is an array of that size; otherwise, if one
type is a variable length array the composite type is that
type.
End of change.
%%
%% Change #4
%%
6.3 Expressions
6.3.3.4 The "sizeof" operator
Semantics
[#2] The "sizeof" operator yields the size (in bytes) of its
operand, which may be an expression or the parenthesized
name of a type.
Replace the following words in C9XD9-pre3:
The size is determined from the type of the
operand, which is not itself evaluated. The result is an
integer constant.
With:
The size is determined from the type of the operand.
The result is an integer. If the type of the operand
is a variable length array type, the operand is evaluated;
otherwise, the operand is not evaluated and the result is
an integer constant.
End of change.
%%
%% Change #5
%%
Add the following example to 6.3.3.4:
int fsize3(int n) {
char b[n+3]; /* variable length array */
return sizeof b; /* execution time sizeof */
}
main() {
int size;
size = fsize3(10); /* func returns the value 13 */
}
End of change.
%%
%% Change #6
%%
Add the following forward reference to 6.3.3.4
variable length array (6.5.4.2).
End of change.
%%
%% Change #7
%%
Add the following example to 6.3.6 Additive operators:
Pointer arithmetic is well defined with pointers to
variable length array types.
{
int n = 4, m = 3;
int a[n][m];
int (*p)[m] = a; /* p == &a[0] */
p += 1; /* p == &a[1] */
(*p)[2] = 99; /* a[1][2] == 99 */
n = p - a; /* n == 1 */
}
If array "a" in the above example is declared to be an
array of known constant size, and pointer "p" is declared
to be a pointer to an array of the same known constant
size that points to "a", the results are still the same.
End of change.
%%
%% Change #8
%%
6.4 Constant expressions
[#6] An integral constant expression shall have integral
type and shall only have operands that are integer
constants, enumeration constants, character constants,
"sizeof" expressions
Add the following words to paragraph 6 above:
whose operand does not have variable
length array type or a parenthesized name of such a type,
End of change.
%%
%% Change #9
%%
Add the following forward reference to 6.4
variable length array (6.5.4.2).
End of change.
%%
%% Change #10
%%
6.5 Declarations
6.5.2 Type specifiers
Add the following as a new paragraph to the end of the Constraints:
Only ordinary identifiers (as defined in 6.1.2.3) with
block scope or function prototype scope and without linkage
can have a variably modified type. If an identifier is
declared to be an object with static storage duration, it
shall not have a variable length array type.
End of change.
%%
%% Change #11
%%
Add the following example to 6.5.2 Type specifiers:
All declarations of variably modified (VM) types must be declared at
either block scope or function prototype scope. Array objects
declared with the "static" or "extern" storage class specifier cannot
have a variable length array (VLA) type. However, a object declared
with the "static" storage class specifier can have a VM type (that
is, a pointer to a VLA type). Finally, all identifiers declared
with a VM type must be ordinary identifiers, and can not, therefore,
be members of structures or unions.
extern int n;
int A[n]; /* Error - file scope VLA */
extern int (*p2)[n]; /* Error - file scope VM */
int B[100]; /* OK - file scope but not VM */
void fvla(int m, int C[m][m]) { /* OK - VLA with prototype scope */
typedef int VLA[m][m]; /* OK - block scope typedef VLA */
/* array size m evaluated now */
struct tag {
int (*y)[n]; /* Error - y is not an ordinary identifier */
int z[n]; /* Error - z is not an ordinary identifier */
};
int D[m]; /* OK - auto VLA */
static int E[m]; /* Error - static block scope VLA */
extern int F[m]; /* Error - F has linkage and is a VLA */
int (*s)[m]; /* OK - auto pointer to VLA */
extern int (*r)[m]; /*Error - r has linkage and is a pointer to VLA*/
static int (*q)[m] = &B; /* OK - q is a static block scope VM */
/* ... */
}
End of change.
%%
%% Change #12
%%
Add the following forward references to 6.5.2
variably modified (6.5.4), variable length array (6.5.4.2).
End of change.
%%
%% Change #13
%%
6.5.2.1 Structure and union specifiers
[#7] A member of a structure or union may have any object type
Add the following words to paragraph 7 above:
other than a variably modified type. *Footnote
____________________
* A structure or union can not contain a member with a
variably modified type bacause member names are not ordinary
identifiers as defined in 6.1.2.3
End of change.
%%
%% Change #14
%%
6.5.4 Declarators
[#2] Each declarator declares one identifier, and asserts
that when an operand of the same form as the declarator
appears in an expression, it designates a function or object
with the scope, storage duration, and type indicated by the
declaration specifiers.
Add the following paragraph after paragraph 2 above:
A `full declarator' is a declarator that is not part of
another declarator. The end of a full declarator is a
sequence point. If the nested sequence of declarators in a
full declarator contains a variable length array type, the
type specified by the full declarator is said to be "variably
modified."
End of change.
%%
%% Change #15
%%
Add the following forward reference to 6.5.4
variable length array (6.5.4.2).
End of change.
%%
%% Change 16
%%
6.5.4.2 Array Declarators
Constraints
Replace the following words in C9XD9-pre3:
[#1] The expression delimited by [ and ] (which specifies
the size of an array) shall be an integral constant
expression that has a value greater than zero.
With:
The [ and ] may delimit an expression or *. If [ and ]
delimit an expression (which specifies the size of an
array), it shall have an integral type. If the expression
is a constant expression then it shall have a value greater
than zero.
End of change.
%%
%% Change 17
%%
Semantics
[#2] If, in the declaration ``T D1,'' D1 has the form
Replace the following words in C9XD9-pre3:
D[ constant-expr ]
opt
With:
D[ assignment-expression ]
opt
or
D[*]
End of change.
%%
%% Change 18
%%
and the type specified for ident in the declaration ``T D''
is ``derived-declarator-type-list T,'' then the type
specified for ident is ``derived-declarator-type-list array
of T.'' If the size is not present, the array type is an
incomplete type.
Add the following words to paragraph 2 above:
If * is used instead of a size
expression, the array type is a variable length array type
of unspecified size, which can only be used in declarations
with function prototype scope. If the size expression is an
integer constant expression and the element type has a known
constant size, the array type is not a variable length array
type. Otherwise, the array type is a variable length array
type. If the size expression is not a constant expression,
and it is evaluated at program execution time, it shall
evaluate to a value greater than zero. It is unspecified
whether side effects are produced when the size expression is
evaluated. The size of each instance of a variable length
array type does not change during its lifetime.
End of change.
%%
%% Change 19
%%
[#3] For two array types to be compatible, both shall have
compatible element types, and if both size specifiers are
present
Replace the following words in C9XD9-pre3:
they shall have the same value.
With:
and integer constant expressions, then both size
specifiers shall have the same constant value. If the two
array types are used in a context which requires them to be
compatible, it is undefined behavior if the two size
specifiers evaluate to unequal values.
End of change.
%%
%% Change 20
%%
Add the following as example 3 to 6.5.4.2 Array declarators:
extern int n;
extern int m;
fcompat() {
int a[n][6][m];
int (*p)[4][n+1];
int c[n][n][6][m];
int (*r)[n][n][n+1];
p = a; /* Error - not compatible because 4 != 6 */
r = c; /* compatible, but defined behavior only if n==6 and m==n+1 */
}
End of change.
%%
%% Change 21
%%
6.5.4.3 Function declarators (including prototypes)
[#5] A parameter type list specifies the types of, and may
declare identifiers for, the parameters of the function.
Add the following words to paragraph 5 above:
A declared parameter that is a member of the parameter type
list that is not part of a function definition, may use the
[*] notation in its sequence of declarator specifiers to
specify a variable length array type.
End of change.
%%
%% Change 22
%%
Add the following as examples 4 and 5 to 6.5.4.3 Function declarators:
4. The following prototype has a variably modified parameter.
void addscalar(int n, int m, double a[n][n*m+300], double x);
main() {
double b[4][308];
addscalar(4, 2, b, 2.17);
}
void addscalar(int n, int m, double a[n][n*m+300], double x) {
int i, j, k=n*m+300;
for (i = 0; i < n; i++)
for (j = 0; j < k; j++)
a[i][j] += x; /* a is a pointer to a VLA with
n*m+300 elements */
}
5. The following are all compatible function prototype declarators.
double maximum(int n, int m, double a[n][m]);
double maximum(int n, int m, double a[*][*]);
double maximum(int n, int m, double a[ ][*]);
double maximum(int n, int m, double a[ ][m]);
End of change.
%%
%% Change 23
%%
6.5.6 Type definitions
Add the following Constraint to 6.5.6 Type definitions:
Constraints:
If a typedef name specifies a variably modified type
then it shall have block scope.
End of change.
%%
%% Change 24
%%
[#2] In a declaration whose storage-class specifier is
typedef, each declarator defines an identifier to be a
typedef name that specifies the type specified for the
identifier in the way described in 6.5.4.
Add the following words to paragraph 2 above:
Any array size
expressions associated with variable length array
declarators shall be evaluated with the typedef name at the
beginning of its scope upon each normal entry to the block.
End of change.
%%
%% Change 25
%%
Add the following as examples 5 and 6 to 6.5.6 Type definitions:
5 The following is a block scope declaration of a typedef name "A"
with a variable length array type.
void tdef(int n) {
typedef int A[n]; /* OK - declared with block scope */
A a;
A *p;
p = &a;
}
6. The size expression that is part of the variable length array type
named by typedef name "B" is evaluated each time function "copyt" is
entered. However, the size of the variable length array type
does not change if the value of "n" is subsequently changed.
void copyt(int n) {
typedef int B[n]; /* B is n ints with n evaluated now */
n += 1;
{
B a; /* a is n ints - n without += 1 */
int b[n]; /* a and b are different sizes */
for (i = 1; i < n; i++)
a[i-1] = b[i];
}
}
End of change.
%%
%% Change 26
%%
6.5.7 Initialization
Replace the following words in C9XD9-pre3:
[#3] The type of the entity to be initialized shall be an
object type or an array of unknown size.
With:
The type of the entity to be initialized shall be an
object type that is not a variable length array type,
or an array of unknown size.
End of change.
%%
%% Change 27
%%
6.6.2 Compound statement, or block
[#2] A compound statement (also called a block) allows a set
of statements to be grouped into one syntactic unit, which
may have its own set of declarations and initializations (as
discussed in 6.1.2.4). The initializers of objects that
have automatic storage duration
Add the following words to paragraph 2 above:
, and the variable length
array declarators of ordinary identifiers with block scope
.......
End of change.
%%
%% Change 28
%%
6.6.4.2 The "switch" statement
[#1] The controlling expression of a "switch" statement shall
have integral type
Add the following words to paragraph 1 above:
, and shall not cause a block to
be entered by a jump from outside the block to a statement
that follows a case or default label in the block (or an
enclosed block) if that block contains the declaration of a
variably modified object or variably modified typedef name.
End of change.
%%
%% Change 29
%%
There is no change 29. There used to be a change 29, but after reading
editorial review committee comments, I decided the proposed example was
unnecessary. However, I didn't want to renumber the remaining changes.
End of change.
%%
%% Change 30
%%
6.6.6.1 The goto statement
Add the following constraint as the second sentence to the Constraints of
6.6.6.1 The goto statement:
A "goto" statement shall not cause a block to be entered by
a jump from outside the block to a labeled statement in
the block (or an enclosed block) if that block contains
the declaration of a variably modified object or
variably modified typedef name
End of change.
%%
%% Change 31
%%
Add the following example as the second example to 6.6.6.1 The goto statement:
2. A "goto" statment is not allowed to jump past any
declarations of objects with variably modified types.
A jump within the block, however, is permitted.
goto lab3; /* Error - going INTO scope of variable length array */
{
double a[n];
a[j] = 4.4;
lab3:
a[j] = 3.3;
goto lab4; /* OK - going WITHIN scope of variable length array */
a[j] = 5.5;
lab4:
a[j] = 6.6;
}
goto lab4; /* Error - going INTO scope of variable length array */
End of change.
%%
%% Change 32
%%
6.7.1 Function definitions
[#9] On entry to the function
Add the following words to paragraph 9 above:
all size expressions of its
variably modified parameters are evaluated, and
.....
End of change.
%%
%% Change 33
%%
7.6.2.1 The longjmp function
Add the following example to the longjmp function:
The "longjmp" function that returns control back to the
point of the setjmp invocation might cause memory associated
with a variable length array object to be squandered.
#include <setjmp.h>
jmp_buf buf;
void g(int n);
void h(int n);
int n = 6;
void f(void) {
int x[n]; /* OK - "f" is not terminated */
setjmp(buf);
g(n);
}
void g(int n) {
int a[n]; /* "a" may remain allocated */
h(n);
}
void h(int n) {
int b[n]; /* "b" may remain allocated */
longjmp(buf,2); /* might cause some memory to be lost */
}
End of change.
Language Syntax Summary
-----------------------
X.1.2.2 Declarations
(6.5.4) direct-declarator:
identifier
(declarator)
direct-declarator [assignment-expression ]
opt
direct-declarator [* ]
opt
direct-declarator (parameter-type-list)
direct-declarator (identifier-list )
opt
(6.5.5) direct-abstract-declarator:
(abstract-declarator)
direct-abstract-declarator [assignment-expression ]
opt
direct-abstract-declarator [* ]
opt
direct-abstract-declarator (parameter-type-list )
opt
=================================================================
=== ===
=== Other correspondence you might be interested in reading ===
=== ===
=================================================================
From dmk@dmk.com Tue Apr 1 15:04 CST 1997
Date: Tue, 1 Apr 97 14:03:29 MST
From: dmk@dmk.com (David Keaton)
To: tam@cray.com
Subject: Re: VLA Edits
TMacD> Basically, it allows you to keep adding more precise information.
TMacD> Don't know how useful this is in a program but still needs to be
TMacD> specified.
Thanks. Those examples helped. I agree that the usefulness of
forming a composite type with an array of known constant size and a
VLA is questionable, but should be specified.
TMacD> An example for composite types is:
TMacD>
TMacD> void f(int [ ][*]);
TMacD> void f(int [5][5]);
TMacD>
TMacD> In the above case the composite type is:
TMacD>
TMacD> void f(int [5][5]);
TMacD>
TMacD> and the parameter is no longer a VLA.
It might be worthwhile to add this example just to make it
obvious. However, since I don't think this technique will be used
very often, I won't object if you don't want to add it.
That's the only issue I had with the VLA changes.
David
========================================================================
From tam@cray.com Thu Apr 3 13:38 CST 1997
From: Thomas MacDonald <tam@cray.com>
Subject: Re: VLA Edits
To: dmk@dmk.com (David Keaton)
Date: Thu, 3 Apr 1997 13:37:41 -0600 (CST)
Thanks David. I've thought about this and decided that this is
better left to rationale. So, I'll keep the example around.
Tom MacDonald
tam@cray.com
========================================================================
From Douglas.Walls@Eng.Sun.COM Wed Apr 16 13:43 CDT 1997
Date: Wed, 16 Apr 1997 09:06:46 -0700
From: Douglas.Walls@Eng.Sun.COM (Douglas Walls)
To: dmk@dmk.com, seebs@solon.com, tam@cray.com
Subject: Re: VLA Edits
Tom,
>Comments should be sent to me by April 15.
Naturally, as I draft these comments, we have network problems and I
am unable to send them on time. Apologies for sending them a day late.
Douglas
---> %%
---> %% Change #7
---> %%
--->
---> Add the following example to 6.3.6 Additive operators:
--->
---> Pointer arithmetic is still well defined with pointers to
^^^^^
This reads as if we are trying to convince someone of the merits of
the proposal. Eliminating this word does not change the example's
meaning.
---> variable length array types.
____________________
---> %%
---> %% Change #10
---> %%
--->
---> 6.5 Declarations
--->
---> 6.5.2 Type specifiers
--->
---> Add the following as a Constraint:
Just to make it clear where to place this constraint:
Add the following as a new paragraph to the end of the Constraints:
--->
---> Only ordinary identifiers (as defined in 6.1.2.3) with
---> block scope or function prototype scope and without linkage
---> can have a variably modified type. If an identifier is
---> declared to be an object with static storage duration, it
---> shall not have a variable length array type.
--->
---> End of change.
____________________
---> %%
---> %% Change 20
---> %%
--->
---> Add the following examples to 6.5.4.2 Array declarators:
Just to make it clear where to add this example:
Add the following as example 3 to 6.5.4.2 Array declarators:
____________________
---> %%
---> %% Change 22
---> %%
--->
---> Add the following examples to 6.5.4.3 Function declarators:
Just to make it clear where to add this example:
Add the following as examples 4 and 5 to 6.5.4.3 Function declarators:
____________________
---> %%
---> %% Change 25
---> %%
--->
---> Add the following examples to 6.5.6 Type definitions:
There are four examples int 6.5.6 now, each with a number and
leading. Where are these example suppose to go?
---> void tdef(int n) {
---> typedef int A[n]; /* OK - declared with block scope */
---> A a;
---> A *p;
---> p = &a;
---> }
--->
---> void copyt(int n) {
---> typedef int A[n]; /* A is n ints with n evaluated now */
---> n += 1;
---> {
---> A a; /* a is n ints - n without += 1 */
---> int b[n]; /* a and b are different sizes */
---> for (i = 1; i < n; i++)
---> a[i-1] = b[i];
---> }
---> }
--->
---> End of change.
____________________
---> %%
---> %% Change 27
---> %%
--->
---> 6.6.2 Compound statement, or block
--->
---> [#2] A compound statement (also called a block) allows a set
---> of statements to be grouped into one syntactic unit, which
---> may have its own set of declarations and initializations (as
---> discussed in 6.1.2.4). The initializers of objects that
---> have automatic storage duration,
^
There is no comma in the original text.
--->
---> Add the following words to paragraph 2 above:
--->
---> and the variable length
The comma belongs here --------------^
---> array declarators of ordinary identifiers with block scope
---> .......
End of change.
____________________
---> %%
---> %% Change 28
---> %%
--->
---> 6.6.4.2 The "switch" statement
--->
---> [#1] The controlling expression of a "switch" statement shall
---> have integral type,
^
There is no comma in the original text.
--->
---> Add the following words to paragraph 1 above:
--->
---> and shall not cause a block to
The comma belongs here-------^
---> be entered by a jump from outside the block to a statement
---> that follows a case or default label in the block (or an
---> enclosed block) if that block contains the declaration of a
---> variably modified object or variably modified typedef name.
End of change.
____________________
---> %%
---> %% Change 29
---> %%
--->
---> Add the following example to 6.6.4.2 The switch statement:
This example needs some lead in text. Looking at the examples in
6.6.4.2 it is not clear where this example is suppose to go.
--->
---> switch (n) /* Error - bypasses declaration of a[n] */
---> {
---> int a[n];
---> case 10:
---> a[0] = 1;
---> break;
---> case 20:
---> a[0] = 2;
---> break;
---> default:
---> a[0] = 3;
---> break;
---> }
--->
---> End of change.
____________________
---> %%
---> %% Change 30
---> %%
--->
---> 6.6.6.1 The goto statement
--->
---> Add the following Constraint to 6.6.6.1 The goto statement:
Just to make it clear where to place this constraint:
Add the following Constraint as new constraint 2 to 6.6.6.1 The
goto statement:
____________________
---> %%
---> %% Change 31
---> %%
Where does this change go? How is it to be integrated with the
existing example in 6.6.6.1? Or are we missing some lead in text and
placement?
--->
---> goto lab3; /* Error - going INTO scope of variable length array */
---> {
---> double a[n];
---> a[j] = 4.4;
---> lab3:
---> a[j] = 3.3;
---> goto lab4; /* OK - going WITHIN scope of variable length array */
---> a[j] = 5.5;
---> lab4:
---> a[j] = 6.6;
---> }
---> goto lab4; /* Error - going INTO scope of variable length array */
--->
---> End of change.
From homer@cray.com Fri May 9 17:32 CDT 1997
From: Bill Homer <homer@cray.com>
Subject: Re: And this
To: tam@cray.com (Thomas MacDonald)
Date: Fri, 9 May 1997 17:32:55 -0500 (CDT)
Tom,
I did see a typo and also have a few suggestions, but none are crucial.
They are marked with '|' at the left.
- Bill
> %%
> %% Change #1
> %%
>
> 6.1.2.4 Storage duration of objects
>
> [#3] An object whose identifier is declared with no linkage
> and without the storage-class specifier static has automatic
> storage duration. Storage is guaranteed to be reserved for
> a new instance of such an object on each normal entry into
> the block with which it is associated.
^
| omit punctuation here, because it changes
> Replace the following words in C9XD9-pre3:
^^^^^^^^^^^^^^^^^^^^^^^^^^^
| End the sentence in C9XD9-pre3 here, and replace its final clause:
>
> , or on a jump from
> outside the block to a labeled statement in the block or in
> an enclosed block.
>
> With the new complete sentences:
>
> . If the block with
> which the object is associated is entered by a jump from
> outside the block to a labeled statement in the block or in
> an enclosed block, then storage is guaranteed to be reserved
> provided the object does not have a variable length array
> type. If the object is variably modified and the block is
> entered by a jump to a labeled statement, then the behavior
> is undefined.
>
> End of change.
> %%
> %% Change #4
> %%
>
> 6.3 Expressions
>
> 6.3.3.4 The "sizeof" operator
>
> Semantics
>
> [#2] The "sizeof" operator yields the size (in bytes) of its
> operand, which may be an expression or the parenthesized
> name of a type.
>
> Replace the following words in C9XD9-pre3:
>
> The size is determined from the type of the
> operand, which is not itself evaluated. The result is an
> integer constant.
>
> With:
>
> The size is determined from the type of the operand.
> The result is an integer. If the type of the operand
> is a varaible length array type, the operand is evaluated;
^^^^^^^^
variable
|
> otherwise, the operand is not evaluated and the result is
> an integer constant.
>
> End of change.
> %%
> %% Change #11
> %%
>
> Add the following example to 6.5.2 Type specifiers:
>
> All declarations of Variably Modified (VM) types must be declared at
^^^^^^^^^^^^^^^^^
| Why capitals here? They are not used in other places.
> either block scope or function prototype scope. Array objects
> declared with the "static" or "extern" storage class specifier cannot
> have a Variable Length Array (VLA) type. However, a object declared
^^^^^^^^^^^^^^^^^^^^^
| Why capitals here? They are not used in other places.
> with the "static" storage class specifier can have a VM type (that
> is, a pointer to a VLA type). Finally, all identifiers declared
> with a VM type must be ordinary identifiers, and can not, therefore,
> be members of structures or unions.
>
> extern int n;
> int A[n]; /* Error - file scope VLA */
> extern int (*p2)[n]; /* Error - file scope VM */
> int B[100]; /* OK - file scope but not VM */
>
> void fvla(int m, int C[m][m]) { /* OK - VLA with prototype scope */
> typedef int VLA[m][m]; /* OK - block scope typedef VLA */
> /* array size m evaluated now */
> struct tag {
> int (*y)[n]; /* Error - y is not an ordinary identifier */
> int z[n]; /* Error - z is not an ordinary identifier */
> };
> int D[m]; /* OK - auto VLA */
> static int E[m]; /* Error - static block scope VLA */
> extern int F[m]; /* Error - F has linkage and is a VLA */
> int (*s)[m]; /* OK - auto pointer to VLA */
> extern int (*r)[m]; /*Error - r has linkage and is a pointer to VLA*/
> static int (*q)[m] = &B; /* OK - q is a static block scope VM */
>
> /* ... */
>
> }
>
> End of change.
> %%
> %% Change 22
> %%
>
> Add the following as examples 4 and 5 to 6.5.4.3 Function declarators:
>
> 4. The following prototype has a variably modified parameter.
>
> void addscalar(int n, int m, double a[n][n*m+300], double x);
>
> main() {
> double b[4][308];
> addscalar(4, 2, b, 2.17);
> }
>
> void addscalar(int n, int m, double a[n][n*m+300], double x) {
> int i, j, k=n*m+300;
>
> for (i = 0; i < n; i++)
> for (j = 0; j < k; j++)
> a[i][j] += x; /* a is a pointer to a VLA of size: n*m+300 */
^^^^^^^^^^^^^^^^
| with n*m+300 elements
> }
>
>
> 5. The following are all compatible function prototype declarators.
>
> double maximum(int n, int m, double a[n][m]);
> double maximum(int n, int m, double a[*][*]);
> double maximum(int n, int m, double a[ ][*]);
> double maximum(int n, int m, double a[ ][m]);
>
> End of change.
> %%
> %% Change 28
> %%
>
> 6.6.4.2 The "switch" statement
>
> [#1] The controlling expression of a "switch" statement shall
> have integral type
>
> Add the following words to paragraph 1 above:
>
> , and shall not cause a block to
> be entered by a jump from outside the block to a statement
> that follows a case or default label in the block (or an
> enclosed block) if that block contains the declaration of a
> variably modified object or variably modified typedef name.
| Maybe this is too big a change, but it seems like there is a
| simpler alternative that is also statically checkable:
If a declaration with a variably modified type is associated
with a block that contains a case or default label of a switch
statement, then that block shall contain the entire switch
statement.
> End of change.
> %%
> %% Change 30
> %%
>
> 6.6.6.1 The goto statement
>
> Add the following constraint as the second sentence to the Constraints of
> 6.6.6.1 The goto statement:
>
> A "goto" statement shall not cause a block to be entered by
> a jump from outside the block to a labeled statement in
> the block (or an enclosed block) if that block contains
> the declaration of a variably modified object or
> variably modified typedef name
| Analogous to the switch statement:
If a declaration with a variably modified type is associated
with a block that contains a label named in a goto statement,
then that block shall also contain the goto statement.
> End of change.