3

Recently I answered some question asking how to implement complex const correctness of a structure member. Doing this I used Generic expressions and encountered strange behavior. Here is the sample code:

struct A
{
    union {
        char *m_ptrChar;

        const char *m_cptrChar;
    } ;
};

#define ptrChar_m(a) _Generic(a, struct A *: a->m_ptrChar,        \
                                 const struct A *: a->m_cptrChar,  \
                                 struct A: a.m_ptrChar,        \
                                 const struct A: a.m_cptrChar)

void f(const struct A *ptrA)
{
    ptrChar_m(ptrA) = 'A'; // NOT DESIRED!!
}

On GCC and Clang the generic expression select the case when the type of a must be struct A which doesn't make any sense. When I comment the last two cases though it's working fine. Why is this - is it some bug?

The exact error messages on clang are:

test.c:17:5: error: member reference type 'const struct A *' is a pointer; did you mean to use '->'?
    ptrChar_m(ptrA) = 'A'; // NOT DESIRED!!
    ^
test.c:12:45: note: expanded from macro 'ptrChar_m'
                                 struct A: a.m_ptrCHar,        \
                                            ^
test.c:17:5: error: member reference type 'const struct A *' is a pointer; did you mean to use '->'?
    ptrChar_m(ptrA) = 'A'; // NOT DESIRED!!
    ^
test.c:13:51: note: expanded from macro 'ptrChar_m'
                                 const struct A: a.m_cptrChar)
                                                  ^
test.c:17:21: error: cannot assign to variable 'ptrA' with const-qualified type 'const struct A *'
    ptrChar_m(ptrA) = 'A'; // NOT DESIRED!!
                    ^
test.c:15:24: note: variable 'ptrA' declared const here
void f(const struct A *ptrA)
                       ^
test.c:23:18: error: invalid application of 'sizeof' to a function type [-Werror,-Wpointer-arith]
    return sizeof(main);
4 errors generated.
Community
  • 1
  • 1
AnArrayOfFunctions
  • 3,452
  • 2
  • 29
  • 66
  • 1
    This is a good question, but including compiler output as a screenshot is not so good. Can't you just copy-paste the text into the question? – unwind Feb 26 '16 at 09:43
  • [THIS](http://stackoverflow.com/a/24746034/3436922) may answer your question – LPs Feb 26 '16 at 09:54

1 Answers1

1

Although the non-matching selections are not evaluated, the compiler is still compiling the code. So using the . operator on a pointer to a structure is not allowed.

If your input expression is always a variable, you could take the address of the variable representing the structure instance.

#define AptrChar_m(a) _Generic(a, struct A *: a->m_ptrChar, \
                                  const struct A *: a->m_cptrChar)
#define ptrChar_m(a) AptrChar_m(_Generic(a, struct A *: a, \
                                            const struct A *: a,  \
                                            struct A: &a,        \
                                            const struct A: &a))
jxh
  • 69,070
  • 8
  • 110
  • 193