[cfe-dev] A doubt about cvr-qualified array types.

Eli Friedman eli.friedman at gmail.com
Sun Oct 24 12:08:13 PDT 2010


On Sun, Oct 24, 2010 at 11:03 AM, Abramo Bagnara
<abramo.bagnara at gmail.com> wrote:
> Il 23/10/2010 20:45, Eli Friedman ha scritto:
>> On Sat, Oct 23, 2010 at 10:29 AM, Abramo Bagnara
>> <abramo.bagnara at gmail.com> wrote:
>>> Il 23/10/2010 19:09, Eli Friedman ha scritto:
>>>> On Sat, Oct 23, 2010 at 2:15 AM, Enea Zaffanella <zaffanella at cs.unipr.it> wrote:
>>>>> Hello.
>>>>>
>>>>> We have a doubt regarding qualified array types.
>>>>>
>>>>> Consider the following program:
>>>>> ===============================
>>>>> struct S {
>>>>>  int a[2];
>>>>> };
>>>>>
>>>>> void foo(void) {
>>>>>  const struct S* ps;
>>>>>  const int (*b)[2];
>>>>>  b = &ps->a;
>>>>> }
>>>>> ===============================
>>>>> as well as its ast dump:
>>>>> ===============================
>>>>> struct S {
>>>>>    int a[2];
>>>>> };
>>>>> void foo() (CompoundStmt 0x3c48bf8 <arraytype.c:5:16, line:9:1>
>>>>>  (DeclStmt 0x3c1be20 <line:6:3, col:21>
>>>>>    0x3c1bdd0 "const struct S *ps")
>>>>>  (DeclStmt 0x3c1bf60 <line:7:3, col:20>
>>>>>    0x3c1bf10 "const int (*b)[2]")
>>>>>  (BinaryOperator 0x3c48bc8 <line:8:3, col:12> 'const int (*)[2]' '='
>>>>>    (DeclRefExpr 0x3c1bf80 <col:3> 'const int (*)[2]' Var='b' 0x3c1bf10)
>>>>>    (UnaryOperator 0x3c48ba0 <col:7, col:12> 'int const (*)[2]' prefix '&'
>>>>>      (MemberExpr 0x3c48b30 <col:8, col:12> 'int const[2]' ->a 0x3c1bc10
>>>>>        (DeclRefExpr 0x3c1bfb8 <col:8> 'const struct S *' Var='ps'
>>>>> 0x3c1bdd0)))))
>>>>> ===============================
>>>>>
>>>>> The dump shows a mismatch between the types of the lhs and the rhs of
>>>>> the assignment expression:
>>>>>  - the lhs has type    const int (*)[2]
>>>>>  - the rhs has type    int const (*)[2]
>>>>> that is, in the rhs the const qualifier is applied to the array type,
>>>>> rather than to the array element type. The two types are anyway detected
>>>>> as being equivalent as witnessed by the absence of an implicit cast.
>>>>
>>>> Per C99, those are the same type.
>>>
>>> To be exact C99 6.7.3.8 says something a little different:
>>>
>>> "If the specification of an array type includes any type qualifiers, the
>>> element type is so qualified, not the array type."
>>>
>>> So it seems to exclude the existence of qualified array type...
>>
>> Err, "int const (*)[2]" isn't a qualified array type... it's just an
>> equivalent way of writing "const int (*)[2]".   But yes, the reason
>> it's printed differently is due to the internal representation.
>
> Ok, so unfortunately we have an internal representation that is
> incongruent with C standard. This is related to efficiency issues?

The issue is more with cases like the following:

typedef int foobar[2];
const foobar* x;

If you want to talk about the type of x, you want to print it as
"const foobar*", not "const int (*)[2]".

In terms of putting const qualifiers on the array type itself, it's
mostly just efficiency; it saves creating an extra type, and it
doesn't really make anything much more complicated than we already
have to be able to deal with.

>>> Does this means that we might encounter all the possible combinations
>>> (i.e. element with qualified/unqualified type inside nested arrays with
>>> qualified/unqualified type) and that the qualifiers of arrays types and
>>> item type should be merged to get a "normalized" type (not canonical)
>>> where qualifiers are pushed to the item type as standard mandates?
>>>
>>> There is a method to get such type?
>>
>> Why would you need such a type?
>
> Consider this example:
>
> struct S {
>  volatile int a[2];
> };
>
> void foo(void) {
>  const struct S* ps;
>  &ps->a;
> }
>
> The type of &ps->a has a volatile qualifier attached to builtin int type
> and a const qualifier attached to array type.
>
> It seems to me rather obvious that this is an undesiderable situation
> for library client that ask a sensible type for an Expr AST node.
>
> Note also that methods like QualType::getCVRQualifiersThroughArrayTypes
> does not handle properly this situation and obtain the wrong result.
>
> To tell you the truth I don't see many reasons to synthesize array Types
> with qualifiers instead to push the qualifiers in the right place, but
> probably I'm missing something...

Assuming the APIs aren't buggy, it should essentially be invisible for
code that isn't digging through QualType internals... but as you
correctly point out, there are bugs.  I think the right way to
approach it is to just fix the bugs, though.

-Eli




More information about the cfe-dev mailing list