Module Name: src Committed By: rillig Date: Sat Sep 28 15:51:40 UTC 2024
Modified Files: src/tests/usr.bin/xlint/lint1: decl_arg.c gcc_attribute_var.c msg_192.c msg_231.c src/usr.bin/xlint/lint1: cgram.y debug.c decl.c externs1.h lint1.h Log Message: lint: handle __attribute__((__unused__)) for functions and variables Previously, lint ignored the '__unused' marker, requiring its own /* ARGSUSED */ marker instead. Previously, attributes were interpreted as soon as the closing parenthesis was parsed. For a function definition such as '__unused static void f(void) {}', this was too early, as the attribute was not connected to the function, as the function was not parsed yet. Now, the 'unused' attribute is passed around by the parser, until it is merged into the declarator where it belongs. Due to an inaccuracy in the grammar, the 'used' attribute has to be passed through a parameter_list, even though a parameter list is not related to attributes. Still, it's better than before. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/tests/usr.bin/xlint/lint1/decl_arg.c cvs rdiff -u -r1.12 -r1.13 src/tests/usr.bin/xlint/lint1/gcc_attribute_var.c cvs rdiff -u -r1.11 -r1.12 src/tests/usr.bin/xlint/lint1/msg_192.c cvs rdiff -u -r1.8 -r1.9 src/tests/usr.bin/xlint/lint1/msg_231.c cvs rdiff -u -r1.509 -r1.510 src/usr.bin/xlint/lint1/cgram.y cvs rdiff -u -r1.80 -r1.81 src/usr.bin/xlint/lint1/debug.c cvs rdiff -u -r1.404 -r1.405 src/usr.bin/xlint/lint1/decl.c cvs rdiff -u -r1.232 -r1.233 src/usr.bin/xlint/lint1/externs1.h cvs rdiff -u -r1.227 -r1.228 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/tests/usr.bin/xlint/lint1/decl_arg.c diff -u src/tests/usr.bin/xlint/lint1/decl_arg.c:1.14 src/tests/usr.bin/xlint/lint1/decl_arg.c:1.15 --- src/tests/usr.bin/xlint/lint1/decl_arg.c:1.14 Sat Sep 28 14:25:04 2024 +++ src/tests/usr.bin/xlint/lint1/decl_arg.c Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: decl_arg.c,v 1.14 2024/09/28 14:25:04 rillig Exp $ */ +/* $NetBSD: decl_arg.c,v 1.15 2024/09/28 15:51:40 rillig Exp $ */ # 3 "decl_arg.c" /* @@ -99,8 +99,6 @@ const // The attribute 'format' belongs to the function type. void param_func_attr_unused( - /* FIXME: handle the 'unused' attribute */ - /* expect+1: warning: parameter 'pr' unused in function 'param_func_attr_unused' [231] */ void (*pr)(const char *, ...) __attribute__((__unused__)) __attribute__((__format__(__printf__, 1, 2))) Index: src/tests/usr.bin/xlint/lint1/gcc_attribute_var.c diff -u src/tests/usr.bin/xlint/lint1/gcc_attribute_var.c:1.12 src/tests/usr.bin/xlint/lint1/gcc_attribute_var.c:1.13 --- src/tests/usr.bin/xlint/lint1/gcc_attribute_var.c:1.12 Sat Sep 28 11:20:29 2024 +++ src/tests/usr.bin/xlint/lint1/gcc_attribute_var.c Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: gcc_attribute_var.c,v 1.12 2024/09/28 11:20:29 rillig Exp $ */ +/* $NetBSD: gcc_attribute_var.c,v 1.13 2024/09/28 15:51:40 rillig Exp $ */ # 3 "gcc_attribute_var.c" /* @@ -28,37 +28,18 @@ placement( void println(void); /* - * Since cgram.y 1.294 from 2021-07-10, lint did not accept declarations that - * started with __attribute__, due to a newly and accidentally introduced - * shift/reduce conflict in the grammar. - * * A GCC extension allows statement of the form __attribute__((fallthrough)), - * thus starting with __attribute__. This is the 'shift' in the conflict. - * The 'reduce' in the conflict was begin_type. - * - * Before cgram 1.294, the gcc_attribute was placed outside the pair of - * begin_type/end_type, exactly to resolve this conflict. - * - * Conceptually, it made sense to put the __attribute__((unused)) between - * begin_type and end_type, to make it part of the declaration-specifiers. - * This change introduced the hidden conflict though. - * - * Interestingly, the number of shift/reduce conflicts did not change in - * cgram 1.294, the conflicts were just resolved differently than before. - * - * To prevent this from happening again, make sure that declarations as well - * as statements can start with gcc_attribute. + * therefore, to avoid shift/reduce conflicts in the grammar, the attributes + * cannot be part of the declaration specifiers between begin_type/end_type. */ void ambiguity_for_attribute(void) { - /* expect+1: warning: 'var1' unused in function 'ambiguity_for_attribute' [192] */ __attribute__((unused)) _Bool var1; switch (1) { case 1: println(); - /* expect+1: warning: 'var2' unused in function 'ambiguity_for_attribute' [192] */ __attribute__((unused)) _Bool var2; __attribute__((fallthrough)); case 2: Index: src/tests/usr.bin/xlint/lint1/msg_192.c diff -u src/tests/usr.bin/xlint/lint1/msg_192.c:1.11 src/tests/usr.bin/xlint/lint1/msg_192.c:1.12 --- src/tests/usr.bin/xlint/lint1/msg_192.c:1.11 Fri Sep 27 16:57:00 2024 +++ src/tests/usr.bin/xlint/lint1/msg_192.c Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_192.c,v 1.11 2024/09/27 16:57:00 rillig Exp $ */ +/* $NetBSD: msg_192.c,v 1.12 2024/09/28 15:51:40 rillig Exp $ */ # 3 "msg_192.c" // Test for message: '%s' unused in function '%s' [192] @@ -23,20 +23,10 @@ example(void) /* expect+1: warning: 'local_signal' unused in function 'example' [192] */ handler (*local_signal)(int, handler); - /* FIXME */ - /* expect+1: warning: 'local_scalar_attr' unused in function 'example' [192] */ int local_scalar_attr __attribute__((__unused__)); - /* FIXME */ - /* expect+1: warning: 'local_ptr_attr' unused in function 'example' [192] */ char *local_ptr_attr __attribute__((__unused__)); - /* FIXME */ - /* expect+1: warning: 'local_arr_attr' unused in function 'example' [192] */ char local_arr_attr[5] __attribute__((__unused__)); - /* FIXME */ - /* expect+1: warning: 'local_func_attr' unused in function 'example' [192] */ void (*local_func_attr)(int, double) __attribute__((__unused__)); - /* FIXME */ - /* expect+1: warning: 'local_signal_attr' unused in function 'example' [192] */ void (*(*local_signal_attr)(int sig, void (*handler)(int)))(int) __attribute__((__unused__)); } Index: src/tests/usr.bin/xlint/lint1/msg_231.c diff -u src/tests/usr.bin/xlint/lint1/msg_231.c:1.8 src/tests/usr.bin/xlint/lint1/msg_231.c:1.9 --- src/tests/usr.bin/xlint/lint1/msg_231.c:1.8 Fri Sep 27 16:57:00 2024 +++ src/tests/usr.bin/xlint/lint1/msg_231.c Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_231.c,v 1.8 2024/09/27 16:57:00 rillig Exp $ */ +/* $NetBSD: msg_231.c,v 1.9 2024/09/28 15:51:40 rillig Exp $ */ # 3 "msg_231.c" // Test for message: parameter '%s' unused in function '%s' [231] @@ -24,11 +24,7 @@ example( int param_scalar_attr __attribute__((__unused__)), char *param_ptr_attr __attribute__((__unused__)), char param_arr_attr[5] __attribute__((__unused__)), - /* FIXME */ - /* expect+1: warning: parameter 'param_func_attr' unused in function 'example' [231] */ void (*param_func_attr)(int, double) __attribute__((__unused__)), - /* FIXME */ - /* expect+1: warning: parameter 'param_signal_attr' unused in function 'example' [231] */ void (*param_signal_attr(int sig, void (*handler)(int)))(int) __attribute__((__unused__)) ) { Index: src/usr.bin/xlint/lint1/cgram.y diff -u src/usr.bin/xlint/lint1/cgram.y:1.509 src/usr.bin/xlint/lint1/cgram.y:1.510 --- src/usr.bin/xlint/lint1/cgram.y:1.509 Sat Sep 28 14:25:04 2024 +++ src/usr.bin/xlint/lint1/cgram.y Sat Sep 28 15:51:40 2024 @@ -1,5 +1,5 @@ %{ -/* $NetBSD: cgram.y,v 1.509 2024/09/28 14:25:04 rillig Exp $ */ +/* $NetBSD: cgram.y,v 1.510 2024/09/28 15:51:40 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.509 2024/09/28 14:25:04 rillig Exp $"); +__RCSID("$NetBSD: cgram.y,v 1.510 2024/09/28 15:51:40 rillig Exp $"); #endif #include <limits.h> @@ -165,6 +165,7 @@ new_attribute(const sbuf_t *prefix, cons scl_t y_scl; tspec_t y_tspec; type_qualifiers y_type_qualifiers; + type_attributes y_type_attributes; function_specifier y_function_specifier; parameter_list y_parameter_list; function_call *y_arguments; @@ -202,6 +203,7 @@ new_attribute(const sbuf_t *prefix, cons %printer { fprintf(yyo, "%s", scl_name($$)); } <y_scl> %printer { fprintf(yyo, "%s", tspec_name($$)); } <y_tspec> %printer { fprintf(yyo, "%s", type_qualifiers_string($$)); } <y_type_qualifiers> +%printer { fprintf(yyo, "%s", type_attributes_string($$)); } <y_type_attributes> %printer { fprintf(yyo, "%s", function_specifier_name($$)); } <y_function_specifier> @@ -365,10 +367,10 @@ new_attribute(const sbuf_t *prefix, cons %type <y_type> begin_type_typespec /* No type for begin_type_qualifier_list. */ /* No type for declmod. */ -/* No type for type_attribute_list_opt. */ -/* No type for type_attribute_list. */ -/* No type for type_attribute_opt. */ -/* No type for type_attribute. */ +%type <y_type_attributes> type_attribute_list_opt +%type <y_type_attributes> type_attribute_list +%type <y_type_attributes> type_attribute_opt +%type <y_type_attributes> type_attribute /* No type for begin_type. */ /* No type for end_type. */ /* No type for notype_init_declarator_list. */ @@ -470,11 +472,11 @@ new_attribute(const sbuf_t *prefix, cons /* No type for arg_declaration_list_opt. */ /* No type for arg_declaration_list. */ /* No type for arg_declaration. */ -/* No type for gcc_attribute_specifier_list_opt. */ -/* No type for gcc_attribute_specifier_list. */ -/* No type for gcc_attribute_specifier. */ -/* No type for gcc_attribute_list. */ -/* No type for gcc_attribute. */ +%type <y_type_attributes> gcc_attribute_specifier_list_opt +%type <y_type_attributes> gcc_attribute_specifier_list +%type <y_type_attributes> gcc_attribute_specifier +%type <y_type_attributes> gcc_attribute_list +%type <y_type_attributes> gcc_attribute %type <y_in_system_header> sys %% @@ -951,7 +953,10 @@ begin_type_declaration_specifiers: /* se | begin_type_declmods type_type_specifier { dcs_add_type($2); } -| type_attribute begin_type_declaration_specifiers +| type_attribute begin_type_declaration_specifiers { + if ($1.used) + dcs_set_used(); + } | begin_type_declaration_specifiers declmod | begin_type_declaration_specifiers notype_type_specifier { dcs_add_type($2); @@ -1024,17 +1029,23 @@ declmod: ; type_attribute_list_opt: - /* empty */ + /* empty */ { + $$ = (type_attributes){ .used = false }; + } | type_attribute_list ; type_attribute_list: type_attribute -| type_attribute_list type_attribute +| type_attribute_list type_attribute { + $$ = (type_attributes){ .used = $1.used || $2.used }; + } ; type_attribute_opt: - /* empty */ + /* empty */ { + $$ = (type_attributes){ .used = false }; + } | type_attribute ; @@ -1042,12 +1053,15 @@ type_attribute: /* See C11 6.7 declara gcc_attribute_specifier | T_ALIGNAS T_LPAREN type_type_specifier T_RPAREN { /* C11 6.7.5 */ dcs_add_alignas(build_sizeof($3)); + $$ = (type_attributes){ .used = false }; } | T_ALIGNAS T_LPAREN constant_expression T_RPAREN { /* C11 6.7.5 */ dcs_add_alignas($3); + $$ = (type_attributes){ .used = false }; } | T_PACKED { dcs_add_packed(); + $$ = (type_attributes){ .used = false }; } ; @@ -1484,8 +1498,14 @@ type_direct_declarator: $$ = add_function(symbolrename($1, $3), $2); end_declaration_level(); block_level--; + if ($2.used) + $$->s_used = true; + } +| type_direct_declarator type_attribute { + $$ = $1; + if ($2.used) + $$->s_used = true; } -| type_direct_declarator type_attribute ; @@ -1584,6 +1604,8 @@ notype_param_declarator: direct_param_declarator: identifier type_attribute_list { $$ = declarator_name(getsym($1)); + if ($2.used) + dcs_set_used(); } | identifier { $$ = declarator_name(getsym($1)); @@ -1594,11 +1616,15 @@ direct_param_declarator: | direct_param_declarator T_LBRACK array_size_opt T_RBRACK gcc_attribute_specifier_list_opt { $$ = add_array($1, $3.has_dim, $3.dim); + if ($5.used) + dcs_set_used(); } | direct_param_declarator param_list asm_or_symbolrename_opt { $$ = add_function(symbolrename($1, $3), $2); end_declaration_level(); block_level--; + if ($2.used) + dcs_set_used(); } ; @@ -1700,15 +1726,16 @@ abstract_declaration: /* specific to li abstract_decl_param_list: /* specific to lint */ abstract_decl_lparen T_RPAREN type_attribute_list_opt { - $$ = (parameter_list){ .first = NULL }; + $$ = (parameter_list){ .used = $3.used }; } | abstract_decl_lparen vararg_parameter_type_list T_RPAREN type_attribute_list_opt { $$ = $2; $$.prototype = true; + $$.used = $4.used; } | abstract_decl_lparen error T_RPAREN type_attribute_list_opt { - $$ = (parameter_list){ .first = NULL }; + $$ = (parameter_list){ .used = $4.used }; } ; @@ -2439,13 +2466,17 @@ arg_declaration: /* https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html */ gcc_attribute_specifier_list_opt: - /* empty */ + /* empty */ { + $$ = (type_attributes){ .used = false }; + } | gcc_attribute_specifier_list ; gcc_attribute_specifier_list: gcc_attribute_specifier -| gcc_attribute_specifier_list gcc_attribute_specifier +| gcc_attribute_specifier_list gcc_attribute_specifier { + $$ = (type_attributes){ .used = $1.used || $2.used }; + } ; gcc_attribute_specifier: @@ -2453,36 +2484,47 @@ gcc_attribute_specifier: in_gcc_attribute = true; } gcc_attribute_list { in_gcc_attribute = false; - } T_RPAREN T_RPAREN + } T_RPAREN T_RPAREN { + $$ = $5; + } ; gcc_attribute_list: gcc_attribute -| gcc_attribute_list T_COMMA gcc_attribute +| gcc_attribute_list T_COMMA gcc_attribute { + $$ = (type_attributes){ .used = $1.used || $3.used }; + } ; gcc_attribute: - /* empty */ + /* empty */ { + $$ = (type_attributes){ .used = false }; + } | T_NAME { + $$ = (type_attributes){ .used = false }; const char *name = $1->sb_name; if (is_either(name, "packed", "__packed__")) dcs_add_packed(); else if (is_either(name, "used", "__used__") || is_either(name, "unused", "__unused__")) - dcs_set_used(); + $$.used = true; else if (is_either(name, "fallthrough", "__fallthrough__")) suppress_fallthrough = true; } -| T_NAME T_LPAREN T_RPAREN +| T_NAME T_LPAREN T_RPAREN { + $$ = (type_attributes){ .used = false }; + } | T_NAME T_LPAREN argument_expression_list T_RPAREN { const char *name = $1->sb_name; if (is_either(name, "aligned", "__aligned__") && $3->args_len == 1) dcs_add_alignas($3->args[0]); + $$ = (type_attributes){ .used = false }; } | type_qualifier { if (!$1.tq_const) yyerror("Bad attribute"); + $$ = (type_attributes){ .used = false }; } ; Index: src/usr.bin/xlint/lint1/debug.c diff -u src/usr.bin/xlint/lint1/debug.c:1.80 src/usr.bin/xlint/lint1/debug.c:1.81 --- src/usr.bin/xlint/lint1/debug.c:1.80 Tue Sep 24 19:58:06 2024 +++ src/usr.bin/xlint/lint1/debug.c Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: debug.c,v 1.80 2024/09/24 19:58:06 rillig Exp $ */ +/* $NetBSD: debug.c,v 1.81 2024/09/28 15:51:40 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.80 2024/09/24 19:58:06 rillig Exp $"); +__RCSID("$NetBSD: debug.c,v 1.81 2024/09/28 15:51:40 rillig Exp $"); #endif #include <stdlib.h> @@ -355,6 +355,12 @@ type_qualifiers_string(type_qualifiers t } const char * +type_attributes_string(type_attributes attrs) +{ + return attrs.used ? "used" : "none"; +} + +const char * function_specifier_name(function_specifier spec) { static const char *const name[] = { Index: src/usr.bin/xlint/lint1/decl.c diff -u src/usr.bin/xlint/lint1/decl.c:1.404 src/usr.bin/xlint/lint1/decl.c:1.405 --- src/usr.bin/xlint/lint1/decl.c:1.404 Wed Sep 4 04:15:30 2024 +++ src/usr.bin/xlint/lint1/decl.c Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: decl.c,v 1.404 2024/09/04 04:15:30 rillig Exp $ */ +/* $NetBSD: decl.c,v 1.405 2024/09/28 15:51:40 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.404 2024/09/04 04:15:30 rillig Exp $"); +__RCSID("$NetBSD: decl.c,v 1.405 2024/09/28 15:51:40 rillig Exp $"); #endif #include <sys/param.h> @@ -1382,6 +1382,8 @@ add_function(sym_t *decl, parameter_list params.first = NULL; } else old_style_function(decl, params.first); + if (params.used) + decl->s_used = true; /* * The symbols are removed from the symbol table by @@ -1521,6 +1523,8 @@ declarator_name(sym_t *sym) sym->s_scl = sc; sym->s_type = dcs->d_type; + if (dcs->d_used) + sym->s_used = true; dcs->d_func_proto_syms = NULL; Index: src/usr.bin/xlint/lint1/externs1.h diff -u src/usr.bin/xlint/lint1/externs1.h:1.232 src/usr.bin/xlint/lint1/externs1.h:1.233 --- src/usr.bin/xlint/lint1/externs1.h:1.232 Tue Sep 24 19:58:06 2024 +++ src/usr.bin/xlint/lint1/externs1.h Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: externs1.h,v 1.232 2024/09/24 19:58:06 rillig Exp $ */ +/* $NetBSD: externs1.h,v 1.233 2024/09/28 15:51:40 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -136,6 +136,7 @@ const char *decl_level_kind_name(decl_le const char *scl_name(scl_t); const char *symbol_kind_name(symbol_kind); const char *type_qualifiers_string(type_qualifiers); +const char *type_attributes_string(type_attributes); const char *function_specifier_name(function_specifier); const char *named_constant_name(named_constant); void debug_dcs(void); Index: src/usr.bin/xlint/lint1/lint1.h diff -u src/usr.bin/xlint/lint1/lint1.h:1.227 src/usr.bin/xlint/lint1/lint1.h:1.228 --- src/usr.bin/xlint/lint1/lint1.h:1.227 Sat May 11 16:12:28 2024 +++ src/usr.bin/xlint/lint1/lint1.h Sat Sep 28 15:51:40 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: lint1.h,v 1.227 2024/05/11 16:12:28 rillig Exp $ */ +/* $NetBSD: lint1.h,v 1.228 2024/09/28 15:51:40 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -78,6 +78,10 @@ typedef struct { bool tq_atomic; } type_qualifiers; +typedef struct { + bool used; +} type_attributes; + /* A bool, integer or floating-point value. */ typedef struct { tspec_t v_tspec; @@ -380,6 +384,7 @@ typedef struct { sym_t *first; bool vararg:1; bool prototype:1; + bool used:1; } parameter_list; /*