Skip to content

Commit

Permalink
lint: use separate types for parsing pointer types and type qualifiers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
rillig committed Jul 13, 2023
1 parent dd5011a commit 35c6520
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 132 deletions.
80 changes: 30 additions & 50 deletions usr.bin/xlint/lint1/cgram.y
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -141,7 +141,7 @@ is_either(const char *s, const char *a, const char *b)
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;
Expand All @@ -166,7 +166,7 @@ is_either(const char *s, const char *a, const char *b)
%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>
Expand All @@ -181,10 +181,7 @@ is_either(const char *s, const char *a, const char *b)
%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>
Expand Down Expand Up @@ -234,9 +231,8 @@ is_either(const char *s, const char *a, const char *b)
*/
%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
Expand Down Expand Up @@ -338,13 +334,11 @@ is_either(const char *s, const char *a, const char *b)
%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. */
Expand Down Expand Up @@ -846,7 +840,7 @@ begin_type_declaration_specifiers: /* see C99 6.7 */

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);
Expand All @@ -870,7 +864,7 @@ begin_type_specifier_qualifier_list_postfix:
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);
Expand All @@ -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);
Expand Down Expand Up @@ -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 };
}
;

Expand All @@ -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);
}
;

Expand Down Expand Up @@ -1470,7 +1450,7 @@ array_size:
}
| type_qualifier {
/* C11 6.7.6.2 */
if ($1 != RESTRICT)
if (!$1.tq_restrict)
yyerror("Bad attribute");
$$ = NULL;
}
Expand Down Expand Up @@ -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");
}
;
Expand Down Expand Up @@ -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:
Expand Down
26 changes: 13 additions & 13 deletions usr.bin/xlint/lint1/debug.c
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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",
};

return name[qual];
static char buf[32];

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 *
Expand Down Expand Up @@ -392,8 +392,8 @@ debug_sym(const char *prefix, const sym_t *sym, const char *suffix)
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));
Expand Down
75 changes: 32 additions & 43 deletions usr.bin/xlint/lint1/decl.c
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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. */
}
}

Expand Down Expand Up @@ -1153,45 +1151,36 @@ set_bit_field_width(sym_t *dsym, int bit_field_width)
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 *
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 35c6520

Please sign in to comment.