Module Name: src Committed By: rillig Date: Thu Jul 13 23:11:11 UTC 2023
Modified Files: src/usr.bin/xlint/lint1: cgram.y debug.c decl.c externs1.h lex.c lint1.h Log Message: lint: use separate types for parsing pointer types and type qualifiers The documentation of the previous 'qual_ptr_t' was misleading, as that type was used for other type qualifier lists as well, even if these were not related to pointer types. To generate a diff of this commit: cvs rdiff -u -r1.460 -r1.461 src/usr.bin/xlint/lint1/cgram.y cvs rdiff -u -r1.53 -r1.54 src/usr.bin/xlint/lint1/debug.c cvs rdiff -u -r1.353 -r1.354 src/usr.bin/xlint/lint1/decl.c cvs rdiff -u -r1.194 -r1.195 src/usr.bin/xlint/lint1/externs1.h cvs rdiff -u -r1.184 -r1.185 src/usr.bin/xlint/lint1/lex.c cvs rdiff -u -r1.190 -r1.191 src/usr.bin/xlint/lint1/lint1.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/xlint/lint1/cgram.y diff -u src/usr.bin/xlint/lint1/cgram.y:1.460 src/usr.bin/xlint/lint1/cgram.y:1.461 --- src/usr.bin/xlint/lint1/cgram.y:1.460 Thu Jul 13 08:40:38 2023 +++ src/usr.bin/xlint/lint1/cgram.y Thu Jul 13 23:11:11 2023 @@ -1,5 +1,5 @@ %{ -/* $NetBSD: cgram.y,v 1.460 2023/07/13 08:40:38 rillig Exp $ */ +/* $NetBSD: cgram.y,v 1.461 2023/07/13 23:11:11 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -35,7 +35,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: cgram.y,v 1.460 2023/07/13 08:40:38 rillig Exp $"); +__RCSID("$NetBSD: cgram.y,v 1.461 2023/07/13 23:11:11 rillig Exp $"); #endif #include <limits.h> @@ -141,7 +141,7 @@ is_either(const char *s, const char *a, op_t y_op; scl_t y_scl; tspec_t y_tspec; - tqual_t y_tqual; + type_qualifiers y_type_qualifiers; function_specifier y_function_specifier; type_t *y_type; tnode_t *y_tnode; @@ -166,7 +166,7 @@ is_either(const char *s, const char *a, %printer { fprintf(yyo, "%s", op_name($$)); } <y_op> %printer { fprintf(yyo, "%s", scl_name($$)); } <y_scl> %printer { fprintf(yyo, "%s", tspec_name($$)); } <y_tspec> -%printer { fprintf(yyo, "%s", tqual_name($$)); } <y_tqual> +%printer { fprintf(yyo, "%s", type_qualifiers_string($$)); } <y_type_qualifiers> %printer { fprintf(yyo, "%s", function_specifier_name($$)); } <y_function_specifier> @@ -181,10 +181,7 @@ is_either(const char *s, const char *a, %printer { fprintf(yyo, "%zu to %zu", $$.lo, $$.hi); } <y_range> %printer { fprintf(yyo, "length %zu", $$->st_len); } <y_string> %printer { - fprintf(yyo, "%s%s%s", - $$->p_const ? "const " : "", - $$->p_volatile ? "volatile " : "", - $$->p_pointer ? "*" : ""); + fprintf(yyo, "%s *", type_qualifiers_string($$->qualifiers)); } <y_qual_ptr> %printer { fprintf(yyo, "%s", $$ ? "yes" : "no"); } <y_seen_statement> %printer { fprintf(yyo, "%s", type_name($$->ga_arg)); } <y_generic> @@ -234,9 +231,8 @@ is_either(const char *s, const char *a, */ %token <y_tspec> T_TYPE -/* qualifiers (const, volatile, restrict, _Thread_local) */ -%token <y_tqual> T_QUAL -%token <y_tqual> T_ATOMIC +%token <y_type_qualifiers> T_QUAL +%token <y_type_qualifiers> T_ATOMIC /* struct or union */ %token <y_tspec> T_STRUCT_OR_UNION @@ -338,13 +334,11 @@ is_either(const char *s, const char *a, %type <y_sym> enums_with_opt_comma %type <y_sym> enumerator_list %type <y_sym> enumerator -%type <y_tqual> type_qualifier +%type <y_type_qualifiers> type_qualifier /* No type for atomic. */ %type <y_qual_ptr> pointer -%type <y_qual_ptr> asterisk -%type <y_qual_ptr> type_qualifier_list_opt -%type <y_qual_ptr> type_qualifier_list -%type <y_qual_ptr> type_qualifier_list_elem +%type <y_type_qualifiers> type_qualifier_list_opt +%type <y_type_qualifiers> type_qualifier_list /* No type for notype_init_declarators. */ /* No type for type_init_declarators. */ /* No type for notype_init_declarator. */ @@ -846,7 +840,7 @@ begin_type_declaration_specifiers: /* se begin_type_declmods: /* see C99 6.7 */ begin_type type_qualifier { - dcs_add_qualifier($2); + dcs_add_qualifiers($2); } | begin_type T_SCLASS { dcs_add_storage_class($2); @@ -870,7 +864,7 @@ begin_type_specifier_qualifier_list_post dcs_add_type($2); } | begin_type_specifier_qualifier_list_postfix type_qualifier { - dcs_add_qualifier($2); + dcs_add_qualifiers($2); } | begin_type_specifier_qualifier_list_postfix notype_type_specifier { dcs_add_type($2); @@ -889,16 +883,16 @@ begin_type_typespec: begin_type_qualifier_list: begin_type type_qualifier { - dcs_add_qualifier($2); + dcs_add_qualifiers($2); } | begin_type_qualifier_list type_qualifier { - dcs_add_qualifier($2); + dcs_add_qualifiers($2); } ; declmod: type_qualifier { - dcs_add_qualifier($1); + dcs_add_qualifiers($1); } | T_SCLASS { dcs_add_storage_class($1); @@ -1223,7 +1217,7 @@ enumerator: /* C99 6.7.2.2 */ type_qualifier: /* C99 6.7.3 */ T_QUAL | atomic { - $$ = ATOMIC; + $$ = (type_qualifiers){ .tq_atomic = true }; } ; @@ -1237,43 +1231,29 @@ atomic: /* helper */ ; pointer: /* C99 6.7.5 */ - asterisk type_qualifier_list_opt { - $$ = merge_qualified_pointer($1, $2); - } -| asterisk type_qualifier_list_opt pointer { - $$ = merge_qualified_pointer($1, $2); - $$ = merge_qualified_pointer($$, $3); + T_ASTERISK type_qualifier_list_opt { + $$ = xcalloc(1, sizeof(*$$)); + add_type_qualifiers(&$$->qualifiers, $2); } -; - -asterisk: /* helper for 'pointer' */ - T_ASTERISK { +| T_ASTERISK type_qualifier_list_opt pointer { $$ = xcalloc(1, sizeof(*$$)); - $$->p_pointer = true; + add_type_qualifiers(&$$->qualifiers, $2); + $$ = append_qualified_pointer($$, $3); } ; type_qualifier_list_opt: /* see C99 6.7.5 */ /* empty */ { - $$ = NULL; + $$ = (type_qualifiers){ .tq_const = false }; } | type_qualifier_list ; type_qualifier_list: /* C99 6.7.5 */ - type_qualifier_list_elem -| type_qualifier_list type_qualifier_list_elem { - $$ = merge_qualified_pointer($1, $2); - } -; - -type_qualifier_list_elem: /* helper for 'pointer' */ - type_qualifier { - $$ = xcalloc(1, sizeof(*$$)); - if ($1 == CONST) - $$->p_const = true; - if ($1 == VOLATILE) - $$->p_volatile = true; + type_qualifier +| type_qualifier_list type_qualifier { + $$ = $1; + add_type_qualifiers(&$$, $2); } ; @@ -1470,7 +1450,7 @@ array_size: } | type_qualifier { /* C11 6.7.6.2 */ - if ($1 != RESTRICT) + if (!$1.tq_restrict) yyerror("Bad attribute"); $$ = NULL; } @@ -2210,7 +2190,7 @@ gcc_attribute: | T_NAME T_LPAREN T_RPAREN | T_NAME T_LPAREN gcc_attribute_parameters T_RPAREN | type_qualifier { - if ($1 != CONST) + if (!$1.tq_const) yyerror("Bad attribute"); } ; @@ -2259,7 +2239,7 @@ cgram_to_string(int token, YYSTYPE val) case T_STRUCT_OR_UNION: return tspec_name(val.y_tspec); case T_QUAL: - return tqual_name(val.y_tqual); + return type_qualifiers_string(val.y_type_qualifiers); case T_FUNCTION_SPECIFIER: return function_specifier_name(val.y_function_specifier); case T_NAME: Index: src/usr.bin/xlint/lint1/debug.c diff -u src/usr.bin/xlint/lint1/debug.c:1.53 src/usr.bin/xlint/lint1/debug.c:1.54 --- src/usr.bin/xlint/lint1/debug.c:1.53 Thu Jul 13 19:59:08 2023 +++ src/usr.bin/xlint/lint1/debug.c Thu Jul 13 23:11:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: debug.c,v 1.53 2023/07/13 19:59:08 rillig Exp $ */ +/* $NetBSD: debug.c,v 1.54 2023/07/13 23:11:11 rillig Exp $ */ /*- * Copyright (c) 2021 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: debug.c,v 1.53 2023/07/13 19:59:08 rillig Exp $"); +__RCSID("$NetBSD: debug.c,v 1.54 2023/07/13 23:11:11 rillig Exp $"); #endif #include <stdlib.h> @@ -303,16 +303,16 @@ symt_name(symt_t kind) } const char * -tqual_name(tqual_t qual) +type_qualifiers_string(type_qualifiers tq) { - static const char *const name[] = { - "const", - "volatile", - "restrict", - "_Atomic", - }; + static char buf[32]; - return name[qual]; + snprintf(buf, sizeof(buf), "%s%s%s%s", + tq.tq_const ? " const" : "", + tq.tq_restrict ? " restrict" : "", + tq.tq_volatile ? " volatile" : "", + tq.tq_atomic ? " atomic" : ""); + return buf[0] != '\0' ? buf + 1 : "none"; } const char * @@ -392,8 +392,8 @@ debug_sym(const char *prefix, const sym_ debug_printf(" %s", tspec_name(sym->u.s_keyword.u.sk_tspec)); if (t == T_QUAL) - debug_printf(" %s", - tqual_name(sym->u.s_keyword.u.sk_qualifier)); + debug_printf(" %s", type_qualifiers_string( + sym->u.s_keyword.u.sk_type_qualifier)); if (t == T_FUNCTION_SPECIFIER) debug_printf(" %s", function_specifier_name( sym->u.s_keyword.u.function_specifier)); Index: src/usr.bin/xlint/lint1/decl.c diff -u src/usr.bin/xlint/lint1/decl.c:1.353 src/usr.bin/xlint/lint1/decl.c:1.354 --- src/usr.bin/xlint/lint1/decl.c:1.353 Thu Jul 13 20:30:21 2023 +++ src/usr.bin/xlint/lint1/decl.c Thu Jul 13 23:11:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: decl.c,v 1.353 2023/07/13 20:30:21 rillig Exp $ */ +/* $NetBSD: decl.c,v 1.354 2023/07/13 23:11:11 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.353 2023/07/13 20:30:21 rillig Exp $"); +__RCSID("$NetBSD: decl.c,v 1.354 2023/07/13 23:11:11 rillig Exp $"); #endif #include <sys/param.h> @@ -499,24 +499,22 @@ dcs_set_used(void) * declarators. */ void -dcs_add_qualifier(tqual_t q) +dcs_add_qualifiers(type_qualifiers qs) { - if (q == CONST) { + if (qs.tq_const) { if (dcs->d_const) { /* duplicate '%s' */ warning(10, "const"); } dcs->d_const = true; - } else if (q == VOLATILE) { + } + if (qs.tq_volatile) { if (dcs->d_volatile) { /* duplicate '%s' */ warning(10, "volatile"); } dcs->d_volatile = true; - } else { - lint_assert(q == RESTRICT || q == ATOMIC); - /* Silently ignore these qualifiers. */ } } @@ -1153,45 +1151,36 @@ set_bit_field_width(sym_t *dsym, int bit return dsym; } -/* - * A sequence of asterisks and qualifiers, from right to left. For example, - * 'const ***volatile **const volatile' results in [cvp, p, vp, p, p]. The - * leftmost 'const' is not included in this list, it is stored in dcs->d_const - * instead. - */ +void +add_type_qualifiers(type_qualifiers *dst, type_qualifiers src) +{ + + if (src.tq_const && dst->tq_const) + /* duplicate '%s' */ + warning(10, "const"); + if (src.tq_volatile && dst->tq_volatile) + /* duplicate '%s' */ + warning(10, "volatile"); + + dst->tq_const = dst->tq_const || src.tq_const; + dst->tq_restrict = dst->tq_restrict || src.tq_restrict; + dst->tq_volatile = dst->tq_volatile || src.tq_volatile; + dst->tq_atomic = dst->tq_atomic || src.tq_atomic; +} + qual_ptr * -merge_qualified_pointer(qual_ptr *p1, qual_ptr *p2) +append_qualified_pointer(qual_ptr *p1, qual_ptr *p2) { if (p2 == NULL) - return p1; /* for optional qualifiers */ + return p1; - if (p2->p_pointer) { - /* append p1 to p2, keeping p2 */ - qual_ptr *tail = p2; - while (tail->p_next != NULL) - tail = tail->p_next; - tail->p_next = p1; - return p2; - } - - /* merge p2 into p1, keeping p1 */ - if (p2->p_const) { - if (p1->p_const) { - /* duplicate '%s' */ - warning(10, "const"); - } - p1->p_const = true; - } - if (p2->p_volatile) { - if (p1->p_volatile) { - /* duplicate '%s' */ - warning(10, "volatile"); - } - p1->p_volatile = true; - } - free(p2); - return p1; + /* append p1 to p2, keeping p2 */ + qual_ptr *tail = p2; + while (tail->p_next != NULL) + tail = tail->p_next; + tail->p_next = p1; + return p2; } static type_t * @@ -1229,7 +1218,7 @@ add_pointer(sym_t *decl, qual_ptr *p) while (p != NULL) { *tpp = block_derive_pointer(dcs->d_type, - p->p_const, p->p_volatile); + p->qualifiers.tq_const, p->qualifiers.tq_volatile); tpp = &(*tpp)->t_subt; Index: src/usr.bin/xlint/lint1/externs1.h diff -u src/usr.bin/xlint/lint1/externs1.h:1.194 src/usr.bin/xlint/lint1/externs1.h:1.195 --- src/usr.bin/xlint/lint1/externs1.h:1.194 Thu Jul 13 08:40:38 2023 +++ src/usr.bin/xlint/lint1/externs1.h Thu Jul 13 23:11:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: externs1.h,v 1.194 2023/07/13 08:40:38 rillig Exp $ */ +/* $NetBSD: externs1.h,v 1.195 2023/07/13 23:11:11 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -122,7 +122,7 @@ void expr_restore_memory(memory_pool); const char *decl_level_kind_name(decl_level_kind); const char *scl_name(scl_t); const char *symt_name(symt_t); -const char *tqual_name(tqual_t); +const char *type_qualifiers_string(type_qualifiers); const char *function_specifier_name(function_specifier); void debug_dcs(bool); void debug_node(const tnode_t *); @@ -196,7 +196,7 @@ bool is_incomplete(const type_t *); void dcs_add_function_specifier(function_specifier); void dcs_add_storage_class(scl_t); void dcs_add_type(type_t *); -void dcs_add_qualifier(tqual_t); +void dcs_add_qualifiers(type_qualifiers); void dcs_add_packed(void); void dcs_set_used(void); void begin_declaration_level(decl_level_kind); @@ -211,7 +211,8 @@ void check_type(sym_t *); sym_t *declare_unnamed_member(void); sym_t *declare_member(sym_t *); sym_t *set_bit_field_width(sym_t *, int); -qual_ptr *merge_qualified_pointer(qual_ptr *, qual_ptr *); +void add_type_qualifiers(type_qualifiers *, type_qualifiers); +qual_ptr *append_qualified_pointer(qual_ptr *, qual_ptr *); sym_t *add_pointer(sym_t *, qual_ptr *); sym_t *add_array(sym_t *, bool, int); sym_t *add_function(sym_t *, sym_t *); Index: src/usr.bin/xlint/lint1/lex.c diff -u src/usr.bin/xlint/lint1/lex.c:1.184 src/usr.bin/xlint/lint1/lex.c:1.185 --- src/usr.bin/xlint/lint1/lex.c:1.184 Thu Jul 13 20:30:21 2023 +++ src/usr.bin/xlint/lint1/lex.c Thu Jul 13 23:11:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: lex.c,v 1.184 2023/07/13 20:30:21 rillig Exp $ */ +/* $NetBSD: lex.c,v 1.185 2023/07/13 23:11:11 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: lex.c,v 1.184 2023/07/13 20:30:21 rillig Exp $"); +__RCSID("$NetBSD: lex.c,v 1.185 2023/07/13 23:11:11 rillig Exp $"); #endif #include <ctype.h> @@ -94,7 +94,7 @@ bool in_system_header; #define kwdef_type(name, tspec, since) \ kwdef(name, T_TYPE, .u.kw_tspec = (tspec), since, 0, 1) #define kwdef_tqual(name, tqual, since, gcc, deco) \ - kwdef(name, T_QUAL, .u.kw_tqual = (tqual), since, gcc, deco) + kwdef(name, T_QUAL, .u.kw_tqual = {.tqual = true}, since, gcc, deco) #define kwdef_keyword(name, token) \ kwdef(name, token, {false}, 78, 0, 1) @@ -107,7 +107,7 @@ static const struct keyword { scl_t kw_scl; /* if kw_token is T_SCLASS */ tspec_t kw_tspec; /* if kw_token is T_TYPE or * T_STRUCT_OR_UNION */ - tqual_t kw_tqual; /* if kw_token is T_QUAL */ + type_qualifiers kw_tqual; /* if kw_token is T_QUAL */ function_specifier kw_fs; /* if kw_token is * T_FUNCTION_SPECIFIER */ } u; @@ -132,7 +132,7 @@ static const struct keyword { kwdef_keyword( "case", T_CASE), kwdef_type( "char", CHAR, 78), kwdef_type( "_Complex", COMPLEX, 99), - kwdef_tqual( "const", CONST, 90,0,7), + kwdef_tqual( "const", tq_const, 90,0,7), kwdef_keyword( "continue", T_CONTINUE), kwdef_keyword( "default", T_DEFAULT), kwdef_keyword( "do", T_DO), @@ -157,7 +157,7 @@ static const struct keyword { kwdef_token( "__packed", T_PACKED, 78,0,1), kwdef_token( "__real__", T_REAL, 78,1,1), kwdef_sclass( "register", REG, 78,0,1), - kwdef_tqual( "restrict", RESTRICT, 99,0,7), + kwdef_tqual( "restrict", tq_restrict, 99,0,7), kwdef_keyword( "return", T_RETURN), kwdef_type( "short", SHORT, 78), kwdef( "signed", T_TYPE, .u.kw_tspec = SIGNED, 90,0,3), @@ -178,7 +178,7 @@ static const struct keyword { kwdef("union", T_STRUCT_OR_UNION, .u.kw_tspec = UNION, 78,0,1), kwdef_type( "unsigned", UNSIGN, 78), kwdef_type( "void", VOID, 78), - kwdef_tqual( "volatile", VOLATILE, 90,0,7), + kwdef_tqual( "volatile", tq_volatile, 90,0,7), kwdef_keyword( "while", T_WHILE), #undef kwdef #undef kwdef_token @@ -359,7 +359,7 @@ add_keyword(const struct keyword *kw, bo if (tok == T_SCLASS) sym->s_scl = kw->u.kw_scl; if (tok == T_QUAL) - sym->u.s_keyword.u.sk_qualifier = kw->u.kw_tqual; + sym->u.s_keyword.u.sk_type_qualifier = kw->u.kw_tqual; if (tok == T_FUNCTION_SPECIFIER) sym->u.s_keyword.u.function_specifier = kw->u.kw_fs; @@ -440,7 +440,8 @@ lex_keyword(sym_t *sym) if (tok == T_TYPE || tok == T_STRUCT_OR_UNION) yylval.y_tspec = sym->u.s_keyword.u.sk_tspec; if (tok == T_QUAL) - yylval.y_tqual = sym->u.s_keyword.u.sk_qualifier; + yylval.y_type_qualifiers = + sym->u.s_keyword.u.sk_type_qualifier; if (tok == T_FUNCTION_SPECIFIER) yylval.y_function_specifier = sym->u.s_keyword.u.function_specifier; Index: src/usr.bin/xlint/lint1/lint1.h diff -u src/usr.bin/xlint/lint1/lint1.h:1.190 src/usr.bin/xlint/lint1/lint1.h:1.191 --- src/usr.bin/xlint/lint1/lint1.h:1.190 Thu Jul 13 19:59:08 2023 +++ src/usr.bin/xlint/lint1/lint1.h Thu Jul 13 23:11:11 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: lint1.h,v 1.190 2023/07/13 19:59:08 rillig Exp $ */ +/* $NetBSD: lint1.h,v 1.191 2023/07/13 23:11:11 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -79,13 +79,12 @@ typedef struct strg { void *st_mem; /* char[] for st_char, or wchar_t[] */ } strg_t; -/* type qualifiers (only used during parsing) */ -typedef enum { - CONST, - VOLATILE, - RESTRICT, - ATOMIC, -} tqual_t; +typedef struct { + bool tq_const:1; + bool tq_restrict:1; + bool tq_volatile:1; + bool tq_atomic:1; +} type_qualifiers; /* An integer or floating-point value. */ typedef struct { @@ -257,7 +256,7 @@ typedef struct sym { /* if T_TYPE or T_STRUCT_OR_UNION */ tspec_t sk_tspec; /* if T_QUAL */ - tqual_t sk_qualifier; + type_qualifiers sk_type_qualifier; /* if T_FUNCTION_SPECIFIER */ function_specifier function_specifier; } u; @@ -390,11 +389,14 @@ typedef struct decl_level { struct decl_level *d_enclosing; /* the enclosing declaration level */ } decl_level; -/* One level of pointer indirection in declarators, including qualifiers. */ +/* + * A sequence of asterisks and qualifiers, from right to left. For example, + * 'const ***volatile **const volatile' results in [c-v-, ----, --v-, ----, + * ----]. The leftmost 'const' is not included in this list, it is stored in + * dcs->d_const instead. + */ typedef struct qual_ptr { - bool p_const:1; - bool p_volatile:1; - bool p_pointer:1; + type_qualifiers qualifiers; struct qual_ptr *p_next; } qual_ptr;