Also add some test cases in tests/tests2/39_typedef.c.
Unified · Split
| @@ -3134,6 +3134,17 @@ ST_FUNC int is_btype_size(int bt) · 3133 unmodified lines | ||
| 3134 | 3134 | return bt == VT_SHORT || bt == VT_LONG || bt == VT_LLONG; |
| 3135 | 3135 | } |
| 3136 | 3136 | |
| 3137 | +/* Add type qualifiers to a type. If the type is an array then the qualifiers | |
| 3138 | + are added to the element type, copied because it could be a typedef. */ | |
| 3139 | +static void parse_btype_qualify(CType *type, int qualifiers) | |
| 3140 | +{ | |
| 3141 | + while (type->t & VT_ARRAY) { | |
| 3142 | + type->ref = sym_push(SYM_FIELD, &type->ref->type, 0, type->ref->c); | |
| 3143 | + type = &type->ref->type; | |
| 3144 | + } | |
| 3145 | + type->t |= qualifiers; | |
| 3146 | +} | |
| 3147 | + | |
| 3137 | 3148 | /* return 0 if no type declaration. otherwise, return the basic type |
| 3138 | 3149 | and skip it. |
| 3139 | 3150 | */ |
| @@ -3232,13 +3243,17 @@ static int parse_btype(CType *type, AttributeDef *ad) · 92 unmodified lines | ||
| 3232 | 3243 | case TOK_CONST1: |
| 3233 | 3244 | case TOK_CONST2: |
| 3234 | 3245 | case TOK_CONST3: |
| 3235 | − t |= VT_CONSTANT; | |
| 3246 | + type->t = t; | |
| 3247 | + parse_btype_qualify(type, VT_CONSTANT); | |
| 3248 | + t = type->t; | |
| 3236 | 3249 | next(); |
| 3237 | 3250 | break; |
| 3238 | 3251 | case TOK_VOLATILE1: |
| 3239 | 3252 | case TOK_VOLATILE2: |
| 3240 | 3253 | case TOK_VOLATILE3: |
| 3241 | − t |= VT_VOLATILE; | |
| 3254 | + type->t = t; | |
| 3255 | + parse_btype_qualify(type, VT_VOLATILE); | |
| 3256 | + t = type->t; | |
| 3242 | 3257 | next(); |
| 3243 | 3258 | break; |
| 3244 | 3259 | case TOK_SIGNED1: |
| @@ -3309,18 +3324,14 @@ static int parse_btype(CType *type, AttributeDef *ad) · 64 unmodified lines | ||
| 3309 | 3324 | s = sym_find(tok); |
| 3310 | 3325 | if (!s || !(s->type.t & VT_TYPEDEF)) |
| 3311 | 3326 | goto the_end; |
| 3312 | − t |= (s->type.t & ~VT_TYPEDEF); | |
| 3313 | − if ((t & VT_ARRAY) && | |
| 3314 | − t & (VT_CONSTANT | VT_VOLATILE) & ~s->type.ref->type.t) { | |
| 3315 | − /* This is a case like "typedef int T[1]; const T x;" | |
| 3316 | − in which which we must make a copy of the typedef | |
| 3317 | − type so that we can add the type qualifiers to it. */ | |
| 3318 | − type->ref = sym_push(SYM_FIELD, &s->type.ref->type, | |
| 3319 | − 0, s->type.ref->c); | |
| 3320 | − type->ref->type.t |= t & (VT_CONSTANT | VT_VOLATILE); | |
| 3321 | − } | |
| 3322 | − else | |
| 3323 | − type->ref = s->type.ref; | |
| 3327 | + | |
| 3328 | + type->t = ((s->type.t & ~VT_TYPEDEF) | | |
| 3329 | + (t & ~(VT_CONSTANT | VT_VOLATILE))); | |
| 3330 | + type->ref = s->type.ref; | |
| 3331 | + if (t & (VT_CONSTANT | VT_VOLATILE)) | |
| 3332 | + parse_btype_qualify(type, t & (VT_CONSTANT | VT_VOLATILE)); | |
| 3333 | + t = type->t; | |
| 3334 | + | |
| 3324 | 3335 | if (s->r) { |
| 3325 | 3336 | /* get attributes from typedef */ |
| 3326 | 3337 | if (0 == ad->a.aligned) |
| @@ -28,4 +28,20 @@ int main() · 27 unmodified lines | ||
| 28 | 28 | return 0; |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | +/* "If the specification of an array type includes any type qualifiers, | |
| 32 | + the element type is so-qualified, not the array type." */ | |
| 33 | + | |
| 34 | +typedef int A[3]; | |
| 35 | +extern A const ca; | |
| 36 | +extern const A ca; | |
| 37 | +extern const int ca[3]; | |
| 38 | + | |
| 39 | +typedef A B[1][2]; | |
| 40 | +extern B const cb; | |
| 41 | +extern const B cb; | |
| 42 | +extern const int cb[1][2][3]; | |
| 43 | + | |
| 44 | +extern B b; | |
| 45 | +extern int b[1][2][3]; | |
| 46 | + | |
| 31 | 47 | /* vim: set expandtab ts=4 sw=3 sts=3 tw=80 :*/ |