Am Samstag, den 12.11.2022, 14:54 +0000 schrieb Joseph Myers: > On Sat, 12 Nov 2022, Alejandro Colomar via Gcc wrote: > > > Since it's to be used as an rvalue, not as a lvalue, I guess a > > postfix-expression wouldn't be the right one. > > Several forms of postfix-expression are only rvalues. > > > > (with a special rule about how the identifier is interpreted, different > > > from the normal scope rules)? If so, then ".a = 1" could either match > > > assignment-expression directly (assigning to the postfix-expression ".a"). > > > > No, assigning to a function parameter from within another parameter > > declaration wouldn't make sense. They should be readonly. Side effects > > should be forbidden, I think. > > Such assignments are already allowed. In a function definition, the side > effects (including in size expressions for array parameters adjusted to > pointers) take place before entry to the function body. > > And, in any case, if you did have a constraint disallowing such > assignments, it wouldn't suffice for syntactic disambiguation (see the > previous point I made about that; I have some rough notes towards a WG14 > paper on syntactic disambiguation, but haven't converted them into a > coherent paper). My idea was to only allow array-declarator : direct-declarator [ . identifier ] and only for parameter (not nested inside structs declared in parameter list) as a first step because it seems this would exclude all difficult cases. But if we need to allow more complicated expressions, then it starts getting more complicated. One could could allow more generic expressions, and specify that the .identifier refers to a parameter in the nearest lexically enclosing parameter list or struct/union. Then void foo(struct bar { int x; char c[.x] } a, int x); would not be allowed (which is good because then we could later use the syntax also inside structs). If we apply scoping rules, the following would work: struct bar { int y; }; void foo(char p[((struct bar){ .y = .x }).y], int x); But not: struct bar { int y; }; void foo(char p[((struct bar){ .y = .y }).y], int y); But there are not only syntactical problems, because also the type of the parameter might become relevant and then you can get circular dependencies: void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]); I am not sure what would the best way to fix it. One could specifiy that parameters referred to by the .identifer syntax must of some integer type and that the sub-expression .identifer is always converted to a 'size_t'. Maybe one should also add a constraint that all new type length expressions, i.e. using the syntax, can not have side effects. Or even that they follow all the rules of integer constant expressions with the fictitious assumption that all . identifer sub-expressions are integer constant expressions. The rationale being that this would facilitate compile time reasoning about length expressions. Martin