On 11/13/22 17:34, Alejandro Colomar wrote: > > > On 11/13/22 17:31, Alejandro Colomar wrote: >> >> >> 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. > > Or rather, more easily prohibit explicitly using typeof(), sizeof(), and > _Lengthof() to it. Hmm, this is not enough. Pointer arithmetics are interesting, and for that, you need to implicitly know the sizeof(*.p). How about allowing only integral types or pointers to integral types? > >>> >>>     -  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 >> > --