Re: [PATCH] Various pages: SYNOPSIS: Use VLA syntax in function parameters

Alejandro Colomar
2022-11-13T16:32:04Z

[-- Attachment #1.1: Type: text/plain, Size: 4560 bytes --]

On 11/13/22 17:28, Alejandro Colomar wrote:
> SYNOPSIS:
>
> unary-operator:  . identifier
>
>
> DESCRIPTION:
>
> -  It is not an lvalue.
>
>    -  This means sizeof() and _Lengthof() cannot be applied to them.

Sorry, the above is a thinko.

I wanted to say that, like sizeof() and _Lengthof(), you can't assign to it.

>    -  This prevents ambiguity with a designator in an initializer-list within a
> nested braced-initializer.
>
> -  The type of a .identifier is always an incomplete type.
>
>    -  This prevents circular dependencies involving sizeof() or _Lengthof().
>
> -  Shadowing rules apply.
>
>    -  This prevents ambiguity.
>
>
> EXAMPLES:
>
>
> -  Valid examples (libc):
>
>        int
>        strncmp(const char s1[.n],
>                const char s2[.n],
>                size_t n);
>
>        int
>        cacheflush(void addr[.nbytes],
>                   int nbytes,
>                   int cache);
>
>        long
>        mbind(void addr[.len],
>              unsigned long len,
>              int mode,
>              const unsigned long nodemask[(.maxnode + ULONG_WIDTH ‐ 1)
>                                           / ULONG_WIDTH],
>              unsigned long maxnode, unsigned int flags);
>
>        void *
>        bsearch(const void key[.size],
>                const void base[.size * .nmemb],
>                size_t nmemb,
>                size_t size,
>                int (*compar)(const void [.size], const void [.size]));
>
> -  Valid examples (my own):
>
>        void
>        ustr2str(char dst[restrict .len + 1],
>                 const char src[restrict .len],
>                 size_t len);
>
>        char *
>        stpecpy(char dst[.end - .dst + 1],
>                char *restrict src,
>                char end[1]);
>
> -  Valid examples (from this thread):
>
>    -
>        struct s { int a; };
>        void f(int a, int b[((struct s) { .a = 1 }).a]);
>
>        Explanation:
>        -  Because of shadowing rules, .a=1 refers to the struct member.
>           -  Also, if .a referred to the parameter, it would be an rvalue, so
> it wouldn't be valid to assign to it.
>        -  (...).a refers to the struct member too, since otherwise an rvalue is
> not expected there.
>
>    -
>        void foo(struct bar { int x; char c[.x] } a, int x);
>
>        Explanation:
>        -  Because of shadowing rules, [.x] refers to the struct member.
>
>    -
>        struct bar { int y; };
>        void foo(char p[((struct bar){ .y = .x }).y], int x);
>
>        Explanation:
>        -  .x unambiguously refers to the parameter.
>
> -  Undefined behavior:
>
>    -
>        struct bar { int y; };
>        void foo(char p[((struct bar){ .y = .y }).y], int y);
>
>        Explanation:
>        -  Because of shadowing rules, =.y refers to the struct member.
>        -  .y=.y means initialize the member with itself (uninitialized use).
>        -  (...).y refers to the struct member, since otherwise an rvalue is not
> expected there.
>
> -  Constraint violations:
>
>    -
>        void foo(char (*a)[sizeof *.b], char (*b)[sizeof *.a]);
>
>        Explanation:
>        -  sizeof(*.b): Cannot get size of incomplete type.
>        -  sizeof(*.a): Cannot get size of incomplete type.
>
>    -
>        void f(size_t s, int a[sizeof(1) = 1]);
>
>        Explanation:
>        -  Cannot assign to rvalue.
>
>    -
>        void f(size_t s, int a[.s = 1]);
>
>        Explanation:
>        -  Cannot assign to rvalue.
>
>    -
>        void f(size_t s, int a[sizeof(.s)]);
>
>        Explanation:
>        -  sizeof(.s): Cannot get size of incomplete type.
>
>
> Does this idea make sense to you?
>
>
> Cheers,
> Alex