mirror of
git://repo.or.cz/tinycc.git
synced 2026-11-04 21:26:36 +08:00
tccgen: combine qualifiers through array types
Conditional expressions combine the qualifiers of their pointer target types. TCC only examines the outer array node, although array qualifiers are stored on the element type. This makes the result depend on operand order. Collect and apply qualifiers through array layers.
This commit is contained in:
parent
4666db3288
commit
0cd015b4ed
17
tccgen.c
17
tccgen.c
@ -136,6 +136,8 @@ static void block(int flags);
|
|||||||
static void gen_cast(CType *type);
|
static void gen_cast(CType *type);
|
||||||
static void gen_cast_s(int t);
|
static void gen_cast_s(int t);
|
||||||
static inline CType *pointed_type(CType *type);
|
static inline CType *pointed_type(CType *type);
|
||||||
|
static int type_qualifiers(CType *type);
|
||||||
|
static void parse_btype_qualify(CType *type, int qualifiers);
|
||||||
static int is_compatible_types(CType *type1, CType *type2);
|
static int is_compatible_types(CType *type1, CType *type2);
|
||||||
static int parse_btype(CType *type, AttributeDef *ad, int ignore_label);
|
static int parse_btype(CType *type, AttributeDef *ad, int ignore_label);
|
||||||
static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td);
|
||||||
@ -2972,15 +2974,14 @@ static int combine_types(CType *dest, SValue *op1, SValue *op2, int op)
|
|||||||
pointed to types minus qualifs should be compatible */
|
pointed to types minus qualifs should be compatible */
|
||||||
type = *((pbt1 == VT_VOID) ? type1 : type2);
|
type = *((pbt1 == VT_VOID) ? type1 : type2);
|
||||||
/* combine qualifs */
|
/* combine qualifs */
|
||||||
newquals = ((pt1->t | pt2->t) & (VT_CONSTANT | VT_VOLATILE));
|
newquals = type_qualifiers(pt1) | type_qualifiers(pt2);
|
||||||
if ((~pointed_type(&type)->t & (VT_CONSTANT | VT_VOLATILE))
|
if ((~type_qualifiers(pointed_type(&type))) & newquals)
|
||||||
& newquals)
|
|
||||||
{
|
{
|
||||||
/* copy the pointer target symbol */
|
/* copy the pointer target symbol */
|
||||||
type.ref = sym_push(SYM_FIELD, &type.ref->type,
|
type.ref = sym_push(SYM_FIELD, &type.ref->type,
|
||||||
0, type.ref->c);
|
0, type.ref->c);
|
||||||
copied = 1;
|
copied = 1;
|
||||||
pointed_type(&type)->t |= newquals;
|
parse_btype_qualify(pointed_type(&type), newquals);
|
||||||
}
|
}
|
||||||
/* pointers to incomplete arrays get converted to
|
/* pointers to incomplete arrays get converted to
|
||||||
pointers to completed ones if possible */
|
pointers to completed ones if possible */
|
||||||
@ -3567,6 +3568,14 @@ static inline CType *pointed_type(CType *type)
|
|||||||
return &type->ref->type;
|
return &type->ref->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Array qualifiers are represented on the element type. */
|
||||||
|
static int type_qualifiers(CType *type)
|
||||||
|
{
|
||||||
|
while (type->t & VT_ARRAY)
|
||||||
|
type = pointed_type(type);
|
||||||
|
return type->t & (VT_CONSTANT | VT_VOLATILE);
|
||||||
|
}
|
||||||
|
|
||||||
/* modify type so that its it is a pointer to type. */
|
/* modify type so that its it is a pointer to type. */
|
||||||
ST_FUNC void mk_pointer(CType *type)
|
ST_FUNC void mk_pointer(CType *type)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3956,6 +3956,14 @@ void builtin_test(void)
|
|||||||
COMPAT_TYPE(int[2], const int[2]);
|
COMPAT_TYPE(int[2], const int[2]);
|
||||||
COMPAT_TYPE(int[2][3], volatile int[][3]);
|
COMPAT_TYPE(int[2][3], volatile int[][3]);
|
||||||
COMPAT_TYPE(int (*)[], const int (*)[]);
|
COMPAT_TYPE(int (*)[], const int (*)[]);
|
||||||
|
COMPAT_TYPE(__typeof__(1 ? (const int (*)[2])0 : (int (*)[2])0),
|
||||||
|
const int (*)[2]);
|
||||||
|
COMPAT_TYPE(__typeof__(1 ? (const int (*)[2][3])0 :
|
||||||
|
(volatile int (*)[2][3])0),
|
||||||
|
const volatile int (*)[2][3]);
|
||||||
|
COMPAT_TYPE(__typeof__(1 ? (volatile int (*)[2][3])0 :
|
||||||
|
(const int (*)[2][3])0),
|
||||||
|
const volatile int (*)[2][3]);
|
||||||
COMPAT_TYPE(int *, int *);
|
COMPAT_TYPE(int *, int *);
|
||||||
COMPAT_TYPE(int *, void *);
|
COMPAT_TYPE(int *, void *);
|
||||||
COMPAT_TYPE(int *, const int *);
|
COMPAT_TYPE(int *, const int *);
|
||||||
|
|||||||
@ -661,4 +661,22 @@ void good_volatile_write(volatile my_struct *s)
|
|||||||
s->arr[0] = 1;
|
s->arr[0] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#elif defined test_conditional_array_qualifiers
|
||||||
|
|
||||||
|
typedef int Array2[2];
|
||||||
|
typedef int Array2x3[2][3];
|
||||||
|
|
||||||
|
Array2 *p;
|
||||||
|
const Array2 *cp;
|
||||||
|
const Array2x3 *cap;
|
||||||
|
volatile Array2x3 *vap;
|
||||||
|
|
||||||
|
void test(void)
|
||||||
|
{
|
||||||
|
(1 ? p : cp)[0][0] = 1;
|
||||||
|
(1 ? cp : p)[0][0] = 2;
|
||||||
|
(1 ? cap : vap)[0][0][0] = 3;
|
||||||
|
(1 ? vap : cap)[0][0][0] = 4;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -290,3 +290,9 @@ bar 15 12 34
|
|||||||
60_errors_and_warnings.c:651: warning: assignment discards qualifiers from pointer target type
|
60_errors_and_warnings.c:651: warning: assignment discards qualifiers from pointer target type
|
||||||
|
|
||||||
[test_volatile_array_member_write_ok]
|
[test_volatile_array_member_write_ok]
|
||||||
|
|
||||||
|
[test_conditional_array_qualifiers]
|
||||||
|
60_errors_and_warnings.c:676: warning: assignment of read-only location
|
||||||
|
60_errors_and_warnings.c:677: warning: assignment of read-only location
|
||||||
|
60_errors_and_warnings.c:678: warning: assignment of read-only location
|
||||||
|
60_errors_and_warnings.c:679: warning: assignment of read-only location
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user