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. >> >>     -  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 > --