lint: increase debug logging for declarations

All changes to the global variable 'dcs' are tracked now, to help
identify the cause of the failing tests in expr_sizeof and
gcc_attribute_aligned.

While here, test more invalid type combinations in typedefs.
This commit is contained in:
rillig 2024-05-04 06:52:16 +00:00
parent b108f9c1fe
commit 1772ff8ac7
3 changed files with 182 additions and 45 deletions

View File

@ -1,7 +1,10 @@
/* $NetBSD: msg_004.c,v 1.7 2023/03/28 14:44:34 rillig Exp $ */
/* $NetBSD: msg_004.c,v 1.8 2024/05/04 06:52:17 rillig Exp $ */
# 3 "msg_004.c"
// Test for message: illegal type combination [4]
//
// See also:
// msg_005.c
/* lint1-extra-flags: -X 351 */

View File

@ -1,29 +1,146 @@
/* $NetBSD: msg_005.c,v 1.5 2022/06/17 18:54:53 rillig Exp $ */
/* $NetBSD: msg_005.c,v 1.6 2024/05/04 06:52:17 rillig Exp $ */
# 3 "msg_005.c"
// Test for message: modifying typedef with '%s'; only qualifiers allowed [5]
typedef int number;
typedef char char_alias;
typedef signed char schar_alias;
typedef unsigned char uchar_alias;
typedef short short_alias;
typedef unsigned short ushort_alias;
typedef int int_alias;
typedef unsigned int uint_alias;
typedef long long_alias;
typedef unsigned long ulong_alias;
typedef long long llong_alias;
typedef unsigned long long ullong_alias;
typedef float float_alias;
typedef double double_alias;
typedef long double ldouble_alias;
typedef float _Complex fcomplex_alias;
typedef double _Complex dcomplex_alias;
typedef long double _Complex lcomplex_alias;
/* expect+1: warning: modifying typedef with 'signed'; only qualifiers allowed [5] */
typedef number signed signed_number;
typedef char_alias signed err_s_char;
/* expect+1: warning: modifying typedef with 'unsigned'; only qualifiers allowed [5] */
typedef number unsigned unsigned_number;
typedef char_alias unsigned err_u_char;
/* expect+1: error: illegal type combination [4] */
typedef schar_alias signed err_s_schar;
/* expect+1: error: illegal type combination [4] */
typedef schar_alias unsigned err_u_schar;
/* expect+1: error: illegal type combination [4] */
typedef uchar_alias signed err_s_uchar;
/* expect+1: error: illegal type combination [4] */
typedef uchar_alias unsigned err_u_uchar;
/* expect+1: warning: modifying typedef with 'signed'; only qualifiers allowed [5] */
typedef short_alias signed err_s_short;
/* expect+1: warning: modifying typedef with 'unsigned'; only qualifiers allowed [5] */
typedef short_alias unsigned err_u_short;
/* expect+1: error: illegal type combination [4] */
typedef ushort_alias signed err_s_ushort;
/* expect+1: error: illegal type combination [4] */
typedef ushort_alias unsigned err_u_ushort;
/* expect+1: warning: modifying typedef with 'signed'; only qualifiers allowed [5] */
typedef int_alias signed err_s_int;
/* expect+1: warning: modifying typedef with 'unsigned'; only qualifiers allowed [5] */
typedef int_alias unsigned err_u_int;
/* expect+1: error: illegal type combination [4] */
typedef uint_alias signed err_s_uint;
/* expect+1: error: illegal type combination [4] */
typedef uint_alias unsigned err_u_uint;
/* expect+1: warning: modifying typedef with 'signed'; only qualifiers allowed [5] */
typedef long_alias signed err_s_long;
/* expect+1: warning: modifying typedef with 'unsigned'; only qualifiers allowed [5] */
typedef long_alias unsigned err_u_long;
/* expect+1: error: illegal type combination [4] */
typedef ulong_alias signed err_s_ulong;
/* expect+1: error: illegal type combination [4] */
typedef ulong_alias unsigned err_u_ulong;
/* expect+1: warning: modifying typedef with 'signed'; only qualifiers allowed [5] */
typedef llong_alias signed err_s_llong;
/* expect+1: warning: modifying typedef with 'unsigned'; only qualifiers allowed [5] */
typedef llong_alias unsigned err_u_llong;
/* expect+1: error: illegal type combination [4] */
typedef ullong_alias signed err_s_ullong;
/* expect+1: error: illegal type combination [4] */
typedef ullong_alias unsigned err_u_ullong;
/* expect+1: error: illegal type combination [4] */
typedef float_alias signed err_s_float;
/* expect+1: error: illegal type combination [4] */
typedef float_alias unsigned err_u_float;
/* expect+1: error: illegal type combination [4] */
typedef double_alias signed err_s_double;
/* expect+1: error: illegal type combination [4] */
typedef double_alias unsigned err_u_double;
/* expect+1: error: illegal type combination [4] */
typedef ldouble_alias signed err_s_ldouble;
/* expect+1: error: illegal type combination [4] */
typedef ldouble_alias unsigned err_u_ldouble;
/* expect+1: error: illegal type combination [4] */
typedef fcomplex_alias signed err_s_fcomplex;
/* expect+1: error: illegal type combination [4] */
typedef fcomplex_alias unsigned err_u_fcomplex;
/* expect+1: error: illegal type combination [4] */
typedef dcomplex_alias signed err_s_dcomplex;
/* expect+1: error: illegal type combination [4] */
typedef dcomplex_alias unsigned err_u_dcomplex;
/* expect+1: error: illegal type combination [4] */
typedef lcomplex_alias signed err_s_lcomplex;
/* expect+1: error: illegal type combination [4] */
typedef lcomplex_alias unsigned err_u_lcomplex;
/* expect+1: warning: modifying typedef with 'short'; only qualifiers allowed [5] */
typedef number short short_number;
typedef int_alias short err_short_int;
/* expect+1: error: illegal type combination [4] */
typedef long_alias short err_short_long;
/* expect+1: error: illegal type combination [4] */
typedef float_alias short err_short_float;
/* expect+1: error: illegal type combination [4] */
typedef char_alias long err_l_char;
/* expect+1: error: illegal type combination [4] */
typedef schar_alias long err_l_schar;
/* expect+1: error: illegal type combination [4] */
typedef uchar_alias long err_l_uchar;
/* expect+1: error: illegal type combination [4] */
typedef short_alias long err_l_short;
/* expect+1: error: illegal type combination [4] */
typedef ushort_alias long err_l_ushort;
/* expect+1: warning: modifying typedef with 'long'; only qualifiers allowed [5] */
typedef number long long_number;
typedef int_alias long err_l_int;
/* expect+1: warning: modifying typedef with 'long'; only qualifiers allowed [5] */
typedef uint_alias long err_l_uint;
/* expect+1: warning: modifying typedef with 'long'; only qualifiers allowed [5] */
typedef long_alias long err_l_long;
/* expect+1: warning: modifying typedef with 'long'; only qualifiers allowed [5] */
typedef ulong_alias long err_l_ulong;
/* expect+1: error: illegal type combination [4] */
typedef llong_alias long err_l_llong;
/* expect+1: error: illegal type combination [4] */
typedef ullong_alias long err_l_ullong;
/* expect+1: warning: modifying typedef with 'long'; only qualifiers allowed [5] */
typedef float_alias long err_l_float;
/* expect+1: warning: modifying typedef with 'long'; only qualifiers allowed [5] */
typedef double_alias long err_l_double;
/* expect+1: error: illegal type combination [4] */
typedef ldouble_alias long err_l_ldouble;
/* expect+1: error: illegal type combination [4] */
typedef fcomplex_alias long err_l_fcomplex;
/* expect+1: warning: modifying typedef with 'long'; only qualifiers allowed [5] */
typedef dcomplex_alias long err_l_dcomplex;
/* expect+1: error: illegal type combination [4] */
typedef lcomplex_alias long err_l_lcomplex;
/*
* If the type qualifier comes first, the following name is interpreted as a
* new name, not as the one referring to the typedef. This makes the above
* type modifications even more obscure.
* If the type qualifier comes before the type name, which would be the
* natural order, the type name is interpreted as a new name, not as the one
* referring to the typedef. This makes the above type modifications even
* more unlikely to be accidentally seen in practice.
*/
/* expect+1: error: syntax error 'prefix_long_number' [249] */
typedef long number prefix_long_number;
typedef long int_alias prefix_long_number;
/* Type qualifiers are OK. */
typedef number const const_number;
typedef int_alias const const_int;

View File

@ -1,4 +1,4 @@
/* $NetBSD: decl.c,v 1.401 2024/05/03 04:04:17 rillig Exp $ */
/* $NetBSD: decl.c,v 1.402 2024/05/04 06:52:16 rillig Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
@ -38,7 +38,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID)
__RCSID("$NetBSD: decl.c,v 1.401 2024/05/03 04:04:17 rillig Exp $");
__RCSID("$NetBSD: decl.c,v 1.402 2024/05/04 06:52:16 rillig Exp $");
#endif
#include <sys/param.h>
@ -63,12 +63,20 @@ int enumval;
*/
decl_level *dcs;
#ifdef DEBUG
static inline void
debug_func_dcs(const char *func)
{
debug_printf("%s: ", func);
debug_dcs();
}
#else
#define debug_func_dcs(func) debug_noop()
#endif
void
init_decl(void)
{
/* declaration stack */
dcs = xcalloc(1, sizeof(*dcs));
dcs->d_kind = DLK_EXTERN;
dcs->d_last_dlsym = &dcs->d_first_dlsym;
@ -109,10 +117,10 @@ gettyp(tspec_t t)
type_t *
block_dup_type(const type_t *tp)
{
debug_step("%s '%s'", __func__, type_name(tp));
type_t *ntp = block_zero_alloc(sizeof(*ntp), "type");
// Keep referring to the same subtype, struct, union, enum, params.
*ntp = *tp;
debug_step("%s '%s'", __func__, type_name(ntp));
return ntp;
}
@ -120,10 +128,10 @@ block_dup_type(const type_t *tp)
type_t *
expr_dup_type(const type_t *tp)
{
debug_step("%s '%s'", __func__, type_name(tp));
type_t *ntp = expr_zero_alloc(sizeof(*ntp), "type");
// Keep referring to the same subtype, struct, union, enum, params.
*ntp = *tp;
debug_step("%s: '%s'", __func__, type_name(ntp));
return ntp;
}
@ -136,8 +144,8 @@ expr_dup_type(const type_t *tp)
type_t *
expr_unqualified_type(const type_t *tp)
{
type_t *ntp = expr_zero_alloc(sizeof(*ntp), "type");
// Keep referring to the same subtype, struct, union, enum, params.
*ntp = *tp;
ntp->t_const = false;
ntp->t_volatile = false;
@ -146,11 +154,11 @@ expr_unqualified_type(const type_t *tp)
* In case of a struct or union type, the members should lose their
* qualifiers as well, but that would require a deep copy of the struct
* or union type. This in turn would defeat the type comparison in
* types_compatible, which simply tests whether tp1->u.sou ==
* tp2->u.sou.
* types_compatible, which simply tests whether 'tp1->u.sou ==
* tp2->u.sou'.
*/
debug_step("%s '%s'", __func__, type_name(ntp));
debug_step("%s: '%s'", __func__, type_name(ntp));
return ntp;
}
@ -177,19 +185,15 @@ is_incomplete(const type_t *tp)
void
dcs_add_function_specifier(function_specifier fs)
{
debug_step("%s: %s", __func__, function_specifier_name(fs));
if (fs == FS_INLINE) {
if (dcs->d_inline)
/* duplicate '%s' */
warning(10, "inline");
dcs->d_inline = true;
}
debug_func_dcs(__func__);
}
/*
* Remember the storage class of the current declaration and detect multiple
* storage classes.
*/
void
dcs_add_storage_class(scl_t sc)
{
@ -209,8 +213,7 @@ dcs_add_storage_class(scl_t sc)
dcs->d_scl = STATIC; /* ignore thread_local */
else
dcs->d_multiple_storage_classes = true;
debug_printf("%s: ", __func__);
debug_dcs();
debug_func_dcs(__func__);
}
/* Merge the signedness into the abstract type. */
@ -237,9 +240,6 @@ merge_signedness(tspec_t t, tspec_t s)
static type_t *
typedef_error(type_t *td, tspec_t t)
{
debug_step("%s: '%s' %s", __func__, type_name(td), tspec_name(t));
tspec_t t2 = td->t_tspec;
if ((t == SIGNED || t == UNSIGN) &&
@ -290,6 +290,7 @@ typedef_error(type_t *td, tspec_t t)
invalid:
dcs->d_invalid_type_combination = true;
debug_func_dcs(__func__);
return td;
}
@ -306,8 +307,6 @@ void
dcs_add_type(type_t *tp)
{
debug_step("%s: %s", __func__, type_name(tp));
debug_dcs();
if (tp->t_typedef) {
/*-
* something like "typedef int a; int a b;"
@ -319,11 +318,12 @@ dcs_add_type(type_t *tp)
lint_assert(dcs->d_rank_mod == NO_TSPEC);
dcs->d_type = tp;
debug_func_dcs(__func__);
return;
}
tspec_t t = tp->t_tspec;
if (is_struct_or_union(t) || t == ENUM) {
if (t == STRUCT || t == UNION || t == ENUM) {
/* something like "int struct a ..." */
if (dcs->d_type != NULL || dcs->d_abstract_type != NO_TSPEC ||
dcs->d_rank_mod != NO_TSPEC || dcs->d_sign_mod != NO_TSPEC) {
@ -333,13 +333,14 @@ dcs_add_type(type_t *tp)
dcs->d_rank_mod = NO_TSPEC;
}
dcs->d_type = tp;
debug_dcs();
debug_func_dcs(__func__);
return;
}
if (dcs->d_type != NULL && !dcs->d_type->t_typedef) {
/* something like "struct a int" */
dcs->d_invalid_type_combination = true;
debug_func_dcs(__func__);
return;
}
@ -398,7 +399,7 @@ dcs_add_type(type_t *tp)
dcs->d_invalid_type_combination = true;
dcs->d_abstract_type = t;
}
debug_dcs();
debug_func_dcs(__func__);
}
static void
@ -410,6 +411,8 @@ set_first_typedef(type_t *tp, sym_t *sym)
tp->u.sou->sou_first_typedef = sym;
if (t == ENUM && tp->u.enumer->en_first_typedef == NULL)
tp->u.enumer->en_first_typedef = sym;
debug_printf("%s: ", __func__);
debug_type(tp);
}
static unsigned int
@ -457,7 +460,6 @@ pack_struct_or_union(type_t *tp)
bits = mem_bits;
}
tp->u.sou->sou_size_in_bits = bits;
debug_dcs();
}
void
@ -465,7 +467,9 @@ dcs_add_alignas(tnode_t *tn)
{
dcs->d_mem_align = to_int_constant(tn, true);
if (dcs->d_type != NULL && is_struct_or_union(dcs->d_type->t_tspec))
// FIXME: The type must not be modified.
dcs->d_type->u.sou->sou_align = dcs->d_mem_align;
debug_func_dcs(__func__);
}
void
@ -475,12 +479,14 @@ dcs_add_packed(void)
dcs->d_packed = true;
else
pack_struct_or_union(dcs->d_type);
debug_func_dcs(__func__);
}
void
dcs_set_used(void)
{
dcs->d_used = true;
debug_func_dcs(__func__);
}
/*
@ -492,6 +498,7 @@ void
dcs_add_qualifiers(type_qualifiers qs)
{
add_type_qualifiers(&dcs->d_qual, qs);
debug_func_dcs(__func__);
}
void
@ -591,6 +598,8 @@ dcs_set_asm(void)
for (decl_level *dl = dcs; dl != NULL; dl = dl->d_enclosing)
dl->d_asm = true;
debug_step("%s", __func__);
debug_dcs_all();
}
void
@ -626,6 +635,8 @@ dcs_begin_type(void)
// keep d_last_dlsym
dcs->d_func_proto_syms = NULL;
// keep d_enclosing
debug_func_dcs(__func__);
}
static void
@ -707,8 +718,7 @@ dcs_merge_declaration_specifiers(void)
if (l != NO_TSPEC)
t = l;
dcs->d_type = gettyp(merge_signedness(t, s));
debug_printf("%s: ", __func__);
debug_dcs();
debug_func_dcs(__func__);
}
static void dcs_align(unsigned int, unsigned int);
@ -1036,6 +1046,7 @@ dcs_align(unsigned int member_alignment, unsigned int bit_field_width)
if (bit_field_width == 0
|| dcs->d_sou_size_in_bits + bit_field_width > offset)
dcs->d_sou_size_in_bits = offset;
debug_func_dcs(__func__);
}
/* Add a member to the struct or union type that is being built in 'dcs'. */
@ -1069,7 +1080,7 @@ dcs_add_member(sym_t *mem)
if (union_size > dcs->d_sou_size_in_bits)
dcs->d_sou_size_in_bits = union_size;
debug_dcs();
debug_func_dcs(__func__);
}
sym_t *
@ -1224,7 +1235,7 @@ add_pointer(sym_t *decl, qual_ptr *p)
free(p);
p = next;
}
debug_step("add_pointer: '%s'", type_name(decl->s_type));
debug_step("%s: '%s'", __func__, type_name(decl->s_type));
return decl;
}
@ -1514,6 +1525,7 @@ declarator_name(sym_t *sym)
dcs->d_func_proto_syms = NULL;
debug_sym("declarator_name: ", sym, "\n");
debug_func_dcs(__func__);
return sym;
}
@ -1592,6 +1604,7 @@ new_tag(sym_t *tag, scl_t scl, bool decl, bool semi)
dcs->d_enclosing->d_nonempty_decl = true;
}
debug_sym("new_tag: ", tag, "\n");
debug_dcs_all();
return tag;
}
@ -1669,6 +1682,7 @@ make_tag_type(sym_t *tag, tspec_t kind, bool decl, bool semi)
}
debug_printf("%s: '%s'", __func__, type_name(tp));
debug_sym(" ", tag, "\n");
debug_dcs_all();
return tp;
}
@ -1712,6 +1726,7 @@ complete_struct_or_union(sym_t *first_member)
/* '%s' has no named members */
warning(65, type_name(tp));
debug_step("%s: '%s'", __func__, type_name(tp));
debug_dcs_all();
return tp;
}
@ -1723,6 +1738,7 @@ complete_enum(sym_t *first_enumerator)
tp->u.enumer->en_incomplete = false;
tp->u.enumer->en_first_enumerator = first_enumerator;
debug_step("%s: '%s'", __func__, type_name(tp));
debug_func_dcs(__func__);
return tp;
}
@ -2762,6 +2778,7 @@ abstract_name_level(bool enclosing)
debug_printf("%s: ", __func__);
debug_sym("", sym, "\n");
debug_func_dcs(__func__);
return sym;
}