Module Name: src Committed By: rillig Date: Sat Jun 8 13:50:47 UTC 2024
Modified Files: src/distrib/sets/lists/tests: mi src/tests/usr.bin/xlint/lint1: expr_cast.c gcc.c init.c lang_level_c99.c msg_259.c msg_298.c Added Files: src/tests/usr.bin/xlint/lint1: init_c99.c Removed Files: src/tests/usr.bin/xlint/lint1: d_c99_func.c d_c99_init.c d_c99_struct_init.c d_c99_union_init1.c d_c99_union_init2.c d_c99_union_init3.c d_c99_union_init4.c d_c99_union_init5.c d_cast_lhs.c d_compound_literals1.c d_compound_literals2.c d_constant_conv1.c d_constant_conv2.c d_gcc_variable_array_init.c d_init_array_using_string.c d_init_pop_member.c d_nested_structs.c d_pr_22119.c d_struct_init_nested.c d_type_conv1.c d_type_conv2.c d_type_conv3.c gcc_typeof_after_statement.c Log Message: tests/lint: group tests by topic To generate a diff of this commit: cvs rdiff -u -r1.1317 -r1.1318 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.7 -r0 src/tests/usr.bin/xlint/lint1/d_c99_func.c \ src/tests/usr.bin/xlint/lint1/d_constant_conv2.c \ src/tests/usr.bin/xlint/lint1/d_type_conv1.c \ src/tests/usr.bin/xlint/lint1/d_type_conv2.c cvs rdiff -u -r1.49 -r0 src/tests/usr.bin/xlint/lint1/d_c99_init.c cvs rdiff -u -r1.5 -r0 src/tests/usr.bin/xlint/lint1/d_c99_struct_init.c \ src/tests/usr.bin/xlint/lint1/d_c99_union_init1.c \ src/tests/usr.bin/xlint/lint1/d_compound_literals1.c \ src/tests/usr.bin/xlint/lint1/d_compound_literals2.c \ src/tests/usr.bin/xlint/lint1/d_pr_22119.c cvs rdiff -u -r1.4 -r0 src/tests/usr.bin/xlint/lint1/d_c99_union_init2.c \ src/tests/usr.bin/xlint/lint1/d_c99_union_init4.c \ src/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c \ src/tests/usr.bin/xlint/lint1/d_nested_structs.c cvs rdiff -u -r1.6 -r0 src/tests/usr.bin/xlint/lint1/d_c99_union_init3.c \ src/tests/usr.bin/xlint/lint1/d_cast_lhs.c \ src/tests/usr.bin/xlint/lint1/d_constant_conv1.c \ src/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c cvs rdiff -u -r1.2 -r0 src/tests/usr.bin/xlint/lint1/d_c99_union_init5.c cvs rdiff -u -r1.14 -r0 \ src/tests/usr.bin/xlint/lint1/d_init_array_using_string.c cvs rdiff -u -r1.10 -r0 src/tests/usr.bin/xlint/lint1/d_init_pop_member.c cvs rdiff -u -r1.8 -r0 src/tests/usr.bin/xlint/lint1/d_struct_init_nested.c \ src/tests/usr.bin/xlint/lint1/d_type_conv3.c cvs rdiff -u -r1.5 -r1.6 src/tests/usr.bin/xlint/lint1/expr_cast.c \ src/tests/usr.bin/xlint/lint1/msg_298.c cvs rdiff -u -r1.2 -r1.3 src/tests/usr.bin/xlint/lint1/gcc.c cvs rdiff -u -r1.15 -r1.16 src/tests/usr.bin/xlint/lint1/init.c cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/init_c99.c cvs rdiff -u -r1.4 -r1.5 src/tests/usr.bin/xlint/lint1/lang_level_c99.c cvs rdiff -u -r1.23 -r1.24 src/tests/usr.bin/xlint/lint1/msg_259.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/tests/mi diff -u src/distrib/sets/lists/tests/mi:1.1317 src/distrib/sets/lists/tests/mi:1.1318 --- src/distrib/sets/lists/tests/mi:1.1317 Sat Jun 8 09:09:19 2024 +++ src/distrib/sets/lists/tests/mi Sat Jun 8 13:50:47 2024 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1317 2024/06/08 09:09:19 rillig Exp $ +# $NetBSD: mi,v 1.1318 2024/06/08 13:50:47 rillig Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -6582,32 +6582,32 @@ ./usr/tests/usr.bin/xlint/lint1/d_c99_decls_after_stmt3.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_c99_flex_array_packed.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/d_c99_for_loops.c tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_func.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_init.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_func.c tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_init.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_c99_init.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_c99_nested_struct.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/d_c99_recursive_init.c tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_struct_init.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_struct_init.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_c99_union_cast.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/d_c99_union_cast.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init1.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init2.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init3.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init4.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_c99_union_init5.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init1.c tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init2.c tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init3.c tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init4.c tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/d_c99_union_init5.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_c9x_array_init.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_c9x_recursive_init.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_cast_fun_array_param.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/d_cast_init.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_cast_init2.c tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_cast_lhs.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_cast_lhs.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_cast_lhs.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_cast_typeof.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_compound_literals1.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_compound_literals2.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_constant_conv1.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_compound_literals1.c tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/d_compound_literals2.c tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/d_constant_conv1.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_constant_conv1.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_constant_conv2.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_constant_conv2.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_constant_conv2.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_cvt_constant.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_cvt_constant.exp tests-obsolete obsolete,atf @@ -6624,32 +6624,32 @@ ./usr/tests/usr.bin/xlint/lint1/d_gcc_extension.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_gcc_extension.exp tests-obsolete obsolete ./usr/tests/usr.bin/xlint/lint1/d_gcc_func.c tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_gcc_variable_array_init.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_incorrect_array_size.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_incorrect_array_size.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_init_array_using_string.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_init_array_using_string.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_init_array_using_string.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_init_pop_member.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_init_pop_member.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_init_pop_member.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_lint_assert.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/d_lint_assert.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_long_double_int.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_long_double_int.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_nested_structs.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_nested_structs.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_nolimit_init.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_packed_structs.c tests-usr.bin-tests compattestfile,atf -./usr/tests/usr.bin/xlint/lint1/d_pr_22119.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_pr_22119.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_pr_22119.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_return_type.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_return_type.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_shift_to_narrower_type.c tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_struct_init_nested.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_struct_init_nested.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_struct_init_nested.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_type_conv1.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_type_conv1.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_type_conv1.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_type_conv2.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_type_conv2.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_type_conv2.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/d_type_conv3.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/d_type_conv3.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_type_conv3.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_type_question_colon.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/d_typefun.c tests-usr.bin-tests compattestfile,atf @@ -6729,7 +6729,7 @@ ./usr/tests/usr.bin/xlint/lint1/gcc_stmt_asm.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/gcc_typeof.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/gcc_typeof.exp tests-obsolete obsolete,atf -./usr/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/gcc_typeof_after_statement.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/init.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/init.exp tests-obsolete obsolete,atf @@ -6737,7 +6737,10 @@ ./usr/tests/usr.bin/xlint/lint1/init_braces.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/init_c90.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/init_c90.exp tests-obsolete obsolete,atf +./usr/tests/usr.bin/xlint/lint1/init_c99.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/init_gnu90.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/lang_level_c99.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/lang_level_migr90.c tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/lex_char.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/lex_char.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/lex_char_uchar.c tests-usr.bin-tests compattestfile,atf Index: src/tests/usr.bin/xlint/lint1/expr_cast.c diff -u src/tests/usr.bin/xlint/lint1/expr_cast.c:1.5 src/tests/usr.bin/xlint/lint1/expr_cast.c:1.6 --- src/tests/usr.bin/xlint/lint1/expr_cast.c:1.5 Sun Aug 6 19:44:50 2023 +++ src/tests/usr.bin/xlint/lint1/expr_cast.c Sat Jun 8 13:50:47 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: expr_cast.c,v 1.5 2023/08/06 19:44:50 rillig Exp $ */ +/* $NetBSD: expr_cast.c,v 1.6 2024/06/08 13:50:47 rillig Exp $ */ # 3 "expr_cast.c" /* @@ -31,3 +31,50 @@ cast(void) /* expect+1: error: function 'cast' expects to return value [214] */ return (struct S)local; } + +/* + * https://gnats.netbsd.org/22119 + * + * Before 2021-02-28, lint crashed in cast() since the target type of the + * cast is NULL. +*/ +void +cast_from_error(void) +{ + void (*f1)(void); + + /* expect+1: error: 'p' undefined [99] */ + f1 = (void (*)(void))p; + /* expect+2: error: function returns illegal type 'function(void) returning pointer to void' [15] */ + /* expect+1: error: invalid cast from 'int' to 'function() returning pointer to function(void) returning pointer to void' [147] */ + f1 = (void *()(void))p; /* crash before 2021-02-28 */ +} + +/* + * Pointer casts had been valid lvalues in GCC before 4.0. + * + * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues + * + * C99 6.5.4 "Cast operators" footnote 85 says "A cast does not yield an + * lvalue". + */ + +void take_ptr(const void *); + +void * +lvalue_cast(void *p) +{ + struct str { + int member; + }; + + /* expect+2: error: a cast does not yield an lvalue [163] */ + /* expect+1: error: left operand of '=' must be lvalue [114] */ + ((struct str *)p) = 0; + + /* expect+2: error: a cast does not yield an lvalue [163] */ + /* expect+1: error: operand of '&' must be lvalue [114] */ + take_ptr(&(const void *)p); + + return p; +} Index: src/tests/usr.bin/xlint/lint1/msg_298.c diff -u src/tests/usr.bin/xlint/lint1/msg_298.c:1.5 src/tests/usr.bin/xlint/lint1/msg_298.c:1.6 --- src/tests/usr.bin/xlint/lint1/msg_298.c:1.5 Tue Mar 28 14:44:35 2023 +++ src/tests/usr.bin/xlint/lint1/msg_298.c Sat Jun 8 13:50:47 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_298.c,v 1.5 2023/03/28 14:44:35 rillig Exp $ */ +/* $NetBSD: msg_298.c,v 1.6 2024/06/08 13:50:47 rillig Exp $ */ # 3 "msg_298.c" // Test for message: conversion from '%s' to '%s' may lose accuracy, arg #%d [298] @@ -7,6 +7,7 @@ void take_uchar(unsigned char); void take_schar(signed char); +void take_uint(unsigned int); void convert_bit_and(long l) @@ -20,3 +21,10 @@ convert_bit_and(long l) take_schar(l & 0xFF); take_schar(l & 0x7F); } + +void +convert_floating_to_integer(void) +{ + // TODO: warn about lossy conversion. + take_uint(2.1); +} Index: src/tests/usr.bin/xlint/lint1/gcc.c diff -u src/tests/usr.bin/xlint/lint1/gcc.c:1.2 src/tests/usr.bin/xlint/lint1/gcc.c:1.3 --- src/tests/usr.bin/xlint/lint1/gcc.c:1.2 Sat Jun 8 11:55:40 2024 +++ src/tests/usr.bin/xlint/lint1/gcc.c Sat Jun 8 13:50:47 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: gcc.c,v 1.2 2024/06/08 11:55:40 rillig Exp $ */ +/* $NetBSD: gcc.c,v 1.3 2024/06/08 13:50:47 rillig Exp $ */ # 3 "gcc.c" /* @@ -51,3 +51,44 @@ range_in_case_label(int i) return 2; } } + +union { + int i; + char *s; +} initialize_union_with_mixed_designators[] = { + { i: 1 }, /* GCC-style */ + { s: "foo" }, /* GCC-style */ + { .i = 1 }, /* C99-style */ + { .s = "foo" } /* C99-style */ +}; + +union { + int i[10]; + short s; +} initialize_union_with_gcc_designators[] = { + { s: 2 }, + { i: { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } }, +}; + +void +declaration_of_variable_array(int i) +{ + int array[i]; + while (i-- > 0) + array[i] = 0; +} + +/* + * Before cgram.y 1.226 from 2021-05-03, lint could not parse typeof(...) if + * there was a statement before it. + */ +void * +typeof_after_statement(void **ptr) +{ + return ({ + if (*ptr != (void *)0) + ptr++; + __typeof__(*ptr) ret = *ptr; + ret; + }); +} Index: src/tests/usr.bin/xlint/lint1/init.c diff -u src/tests/usr.bin/xlint/lint1/init.c:1.15 src/tests/usr.bin/xlint/lint1/init.c:1.16 --- src/tests/usr.bin/xlint/lint1/init.c:1.15 Tue Mar 28 14:44:34 2023 +++ src/tests/usr.bin/xlint/lint1/init.c Sat Jun 8 13:50:47 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: init.c,v 1.15 2023/03/28 14:44:34 rillig Exp $ */ +/* $NetBSD: init.c,v 1.16 2024/06/08 13:50:47 rillig Exp $ */ # 3 "init.c" /* @@ -123,3 +123,80 @@ struct { } points_of_unknown_size[] = { 3, 4, }; + +void +init_string_via_assignment(void) +{ + const char *cs_match = ""; + const int *ws_match = L""; + + /* expect+1: warning: illegal combination of 'pointer to const char' and 'pointer to int', op 'init' [124] */ + const char *cs_mismatch = L""; + /* expect+1: warning: illegal combination of 'pointer to const int' and 'pointer to char', op 'init' [124] */ + const int *ws_mismatch = ""; +} + +void +init_pointer_in_struct(void) +{ + struct cs_ws { + const char *cs; + const int *ws; + }; + + struct cs_ws type_match = { + "", + L"", + }; + + struct cs_ws type_mismatch = { + /* expect+1: warning: illegal combination of 'pointer to const char' and 'pointer to int', op 'init' [124] */ + L"", + /* expect+1: warning: illegal combination of 'pointer to const int' and 'pointer to char', op 'init' [124] */ + "", + }; + + struct cs_ws extra_braces = { + { "" }, + { L"" }, + }; +} + + +void +init_array_in_struct(void) +{ + struct cs_ws { + const char cs[10]; + const int ws[10]; + }; + + struct cs_ws type_match = { + "", + L"", + }; + + struct cs_ws type_mismatch = { + /* expect+1: warning: illegal combination of integer 'char' and pointer 'pointer to int' [183] */ + L"", + /* expect+1: warning: illegal combination of integer 'char' and pointer 'pointer to char' [183] */ + "", + }; + + struct cs_ws no_terminating_null = { + "0123456789", + L"0123456789", + }; + + struct cs_ws too_many_characters = { + /* expect+1: warning: string literal too long (11) for target array (10) [187] */ + "0123456789X", + /* expect+1: warning: string literal too long (11) for target array (10) [187] */ + L"0123456789X", + }; + + struct cs_ws extra_braces = { + { "" }, + { L"" }, + }; +} Index: src/tests/usr.bin/xlint/lint1/lang_level_c99.c diff -u src/tests/usr.bin/xlint/lint1/lang_level_c99.c:1.4 src/tests/usr.bin/xlint/lint1/lang_level_c99.c:1.5 --- src/tests/usr.bin/xlint/lint1/lang_level_c99.c:1.4 Sat Jun 8 09:09:20 2024 +++ src/tests/usr.bin/xlint/lint1/lang_level_c99.c Sat Jun 8 13:50:47 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: lang_level_c99.c,v 1.4 2024/06/08 09:09:20 rillig Exp $ */ +/* $NetBSD: lang_level_c99.c,v 1.5 2024/06/08 13:50:47 rillig Exp $ */ # 3 "lang_level_c99.c" /* @@ -146,6 +146,19 @@ hexadecimal_floating_point_constants(voi // [x] compound literals // // See d_c99_compound_literal_comma.c. +struct short_rect { + short top, left, bottom, right; +}; + +struct short_rect *rect_location(void); + +void +compound_literal(void) +{ + struct short_rect me = (struct short_rect){ 1, 2, 3, 4 }; + me.left = me.left; + *rect_location() = (struct short_rect){ 1, 2, 3, 4 }; +} // [x] designated initializers // @@ -279,6 +292,21 @@ const const int duplicate_type_qualifier // [x] __func__ predefined identifier // // Yes, see 'fallback_symbol'. +const char * +function_name(void) +{ + /* expect+1: error: negative array dimension (-14) [20] */ + typedef int reveal_size[-(int)sizeof(__func__)]; + return __func__; +} + + +// Since tree.c 1.504 from 2023-01-29 and before tree.c 1.591 from 2024-01-07, +// lint crashed because there was no "current function", even though the +// "block level" was not 0. +/* expect+1: error: '__func__' undefined [99] */ +typedef int func_outside_function(int[sizeof(__func__)]); + // [x] va_copy macro // Index: src/tests/usr.bin/xlint/lint1/msg_259.c diff -u src/tests/usr.bin/xlint/lint1/msg_259.c:1.23 src/tests/usr.bin/xlint/lint1/msg_259.c:1.24 --- src/tests/usr.bin/xlint/lint1/msg_259.c:1.23 Sun Jul 9 10:42:07 2023 +++ src/tests/usr.bin/xlint/lint1/msg_259.c Sat Jun 8 13:50:47 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_259.c,v 1.23 2023/07/09 10:42:07 rillig Exp $ */ +/* $NetBSD: msg_259.c,v 1.24 2024/06/08 13:50:47 rillig Exp $ */ # 3 "msg_259.c" // Test for message: argument %d is converted from '%s' to '%s' due to prototype [259] @@ -33,6 +33,7 @@ void signed_long(long); void unsigned_long(unsigned long); void signed_long_long(long long); void unsigned_long_long(unsigned long long); +void take_float(float); void change_in_type_width(char c, int i, long l) @@ -230,6 +231,23 @@ unsigned_to_unsigned(unsigned int ui, un } void +constants(void) +{ + /* expect+2: warning: argument 1 is converted from 'long long' to 'unsigned int' due to prototype [259] */ + /* expect+1: warning: conversion of 'long long' to 'unsigned int' is out of range, arg #1 [295] */ + unsigned_int(0x7fffffffffffffffLL); + /* expect+1: warning: argument 1 is converted from 'double' to 'unsigned int' due to prototype [259] */ + unsigned_int(2.1); +} + +void +to_float(double dbl) +{ + /* expect+1: warning: argument 1 is converted from 'double' to 'float' due to prototype [259] */ + take_float(dbl); +} + +void pass_sizeof_as_smaller_type(void) { /* Added files: Index: src/tests/usr.bin/xlint/lint1/init_c99.c diff -u /dev/null src/tests/usr.bin/xlint/lint1/init_c99.c:1.1 --- /dev/null Sat Jun 8 13:50:47 2024 +++ src/tests/usr.bin/xlint/lint1/init_c99.c Sat Jun 8 13:50:47 2024 @@ -0,0 +1,738 @@ +/* $NetBSD: init_c99.c,v 1.1 2024/06/08 13:50:47 rillig Exp $ */ +# 3 "init_c99.c" + +// Tests for initialization in C99 or later, mainly for designators. +// +// See C99 6.7.8 "Initialization". + +/* lint1-flags: -Sw -X 351 */ + +void use(const void *); + +typedef struct any { + const void *value; +} any; + + +// C99 6.7.8p11 says "optionally enclosed in braces". Whether this wording +// means "a single pair of braces" or "as many pairs of braces as you want" +// is left for interpretation to the reader. +int scalar_without_braces = 3; +int scalar_with_optional_braces = { 3 }; +int scalar_with_too_many_braces = {{ 3 }}; +/* expect+1: error: too many initializers for 'int' [174] */ +int scalar_with_too_many_initializers = { 3, 5 }; + + +// See initialization_expr, 'handing over to INIT'. +void +struct_initialization_via_assignment(any arg) +{ + any local = arg; + use(&local); +} + + +// See initialization_expr, initialization_init_array_from_string. +char static_duration[] = "static duration"; +signed char static_duration_signed[] = "static duration"; +unsigned char static_duration_unsigned[] = "static duration"; +int static_duration_wchar[] = L"static duration"; + +// See init_expr. +void +initialization_by_braced_string(void) +{ + any local = { "hello" }; + use(&local); +} + +void +initialization_by_redundantly_braced_string(void) +{ + any local = {{{{ "hello" }}}}; + use(&local); +} + +/* + * Only scalar expressions and string literals may be enclosed by additional + * braces. Since 'arg' is a struct, this is a compile-time error. + */ +void +initialization_with_too_many_braces(any arg) +{ + /* expect+1: error: cannot initialize 'pointer to const void' from 'struct any' [185] */ + any local = { arg }; + use(&arg); +} + +// Some of the following examples are mentioned in the introduction comment +// in init.c. + +int number = 12345; + +int number_with_braces_and_comma = { + 12345, +}; + +int array_with_fixed_size[3] = { + 111, + 222, + 333, + /* expect+1: error: too many array initializers, expected 3 [173] */ + 444, +}; + +// See update_type_of_array_of_unknown_size. +int array_of_unknown_size[] = { + 111, + 222, + 333, +}; + +int array_flat[2][2] = { + 11, + 12, + 21, + 22 +}; + +int array_nested[2][2] = { + { + 11, + 12 + }, + { + 21, + 22 + } +}; + +int array_with_designators[] = { + ['1'] = 111, + ['5'] = 555, + ['9'] = 999 +}; + +int array_with_some_designators[] = { + ['1'] = 111, + 222, + ['9'] = 999 +}; + +struct point { + int x; + int y; +}; + +struct point point = { + 3, + 4 +}; + +struct point point_with_designators = { + .y = 4, + .x = 3, +}; + +struct point point_with_mixed_designators = { + .x = 3, + 4, + /* expect+1: error: too many struct/union initializers [172] */ + 5, + .x = 3, +}; + +/* + * Before cgram.y 1.230 from 2021-06-20, the grammar allowed either of the + * operators '.' or '->' to be used for the designators and had extra code + * to ensure that only '.' was actually used. + */ +struct point origin = { + .x = 0, + /* expect+1: error: syntax error '->' [249] */ + ->y = 0, +}; + +/* Ensure that the parser can recover from the parse error. */ +struct point pythagoras = { 3, 4 }; + +int array_with_designator[] = { + 111, + /* expect+1: error: syntax error 'designator '.member' is only for struct/union' [249] */ + .member = 222, + 333, +}; + +/* + * C99 6.7.8p11 says that the initializer of a scalar can be "optionally + * enclosed in braces". It does not explicitly set an upper limit on the + * number of braces. It also doesn't restrict the term "initializer" to only + * mean the "outermost initializer". 6.7.8p13 defines that a brace for a + * structure or union always means to descend into the type. Both GCC 10 and + * Clang 8 already warn about these extra braces, nevertheless there is + * real-life code (the Postfix MTA) that exploits this corner case of the + * standard. + */ +struct point scalar_with_several_braces = { + {{{3}}}, + {{{{4}}}}, +}; + +struct rectangle { + struct point top_left; + struct point bottom_right; +}; + +/* C99 6.7.8p18 */ +struct rectangle screen = { + .bottom_right = { + 1920, + 1080, + } +}; + +/* + * C99 6.7.8p22 says: At the _end_ of its initializer list, the array no + * longer has incomplete type. + */ +struct point points[] = { + { + /* + * At this point, the size of the object 'points' is not known + * yet since its type is still incomplete. Lint could warn + * about this, but GCC and Clang already do. + * + * Before init.c 1.179 from 2021.03.30, the type information + * of 'points' was set too early, resulting in a negative + * array size below. + */ + sizeof(int[-(int)sizeof(points)]), + 4 + } +}; + + +struct triangle { + struct point points[3]; +}; + +struct pentagon { + struct point points[5]; +}; + +struct geometry { + struct pentagon pentagons[6]; + struct triangle triangles[10]; + struct point points[3][5][2]; +}; + +/* + * Initialization of a complex struct containing nested arrays and nested + * structs. + */ +struct geometry geometry = { + .pentagons[0].points[4].x = 1, + .points[0][0][0] = { 0, 0 }, + .points[2][4][1] = {301, 302 }, + /* expect+1: error: array subscript 3 cannot be > 2 [168] */ + .points[3][0][0] = {3001, 3002 }, + /* expect+1: error: array subscript 5 cannot be > 4 [168] */ + .points[0][5][0] = {501, 502 }, + /* expect+1: error: array subscript 2 cannot be > 1 [168] */ + .points[0][0][2] = {21, 22 }, +}; + +struct ends_with_unnamed_bit_field { + int member; + int:0; +} ends_with_unnamed_bit_field = { + 12345, + /* expect+1: error: too many struct/union initializers [172] */ + 23456, +}; + +char prefixed_message[] = { + 'E', ':', ' ', + /* expect+1: warning: illegal combination of integer 'char' and pointer 'pointer to char' [183] */ + "message\n", +}; + +char message_with_suffix[] = { + "message", + /* The excess character is not detected by lint but by compilers. */ + '\n', +}; + +struct ten { + int i0; + int i1; + int i2; + int i3; + int i4; + int i5; + int i6; + int i7; + int i8; + int i9; +}; + +struct ten ten = { + .i3 = 3, + 4, + 5, + 6, +}; + + +/* + * ISO C99 6.7.8 provides a large list of examples for initialization, + * covering all tricky edge cases. + */ + +int c99_6_7_8_p24_example1_i = 3.5; +double _Complex c99_6_7_8_p24_example1_c = 5 + 3 * 1.0fi; + +int c99_6_7_8_p25_example2[] = { 1, 3, 5 }; + +int c99_6_7_8_p26_example3a[4][3] = { + { 1, 3, 5 }, + { 2, 4, 6 }, + { 3, 5, 7 }, +}; + +int c99_6_7_8_p26_example3b[4][3] = { + 1, 3, 5, 2, 4, 6, 3, 5, 7 +}; + +int c99_6_7_8_p27_example4[4][3] = { + { 1 }, { 2 }, { 3 }, { 4 } +}; + +struct { + int a[3], b; +} c99_6_7_8_p28_example5[] = { + { 1 }, + 2, +}; + +short c99_6_7_8_p29_example6a[4][3][2] = { + { 1 }, + { 2, 3 }, + { 4, 5, 6 }, +}; + +short c99_6_7_8_p29_example6b[4][3][2] = { + 1, 0, 0, 0, 0, 0, + 2, 3, 0, 0, 0, 0, + 4, 5, 6, 0, 0, 0, +}; + +short c99_6_7_8_p29_example6c[4][3][2] = { + { + { 1 }, + }, + { + { 2, 3 }, + }, + { + { 4, 5 }, + { 6 }, + } +}; + +void +c99_6_7_8_p31_example7(void) +{ + typedef int A[]; + + A a = { 1, 2 }, b = { 3, 4, 5 }; + + /* expect+1: error: negative array dimension (-8) [20] */ + typedef int reveal_sizeof_a[-(int)(sizeof(a))]; + /* expect+1: error: negative array dimension (-12) [20] */ + typedef int reveal_sizeof_b[-(int)(sizeof(b))]; +} + +char c99_6_7_8_p32_example8_s1[] = "abc", + c99_6_7_8_p32_example8_t1[3] = "abc"; +char c99_6_7_8_p32_example8_s2[] = { 'a', 'b', 'c', '\0' }, + c99_6_7_8_p32_example8_t2[3] = { 'a', 'b', 'c' }; +char *c99_6_7_8_p32_example8_p = "abc"; + +enum { member_one, member_two }; +const char *c99_6_7_8_p33_example9[] = { + [member_two] = "member two", + [member_one] = "member one", +}; + +struct { + int quot, rem; +} c99_6_7_8_p34_example10 = { .quot = 2, .rem = -1 }; + +struct { int a[3], b; } c99_6_7_8_p35_example11[] = + { [0].a = {1}, [1].a[0] = 2 }; + +int c99_6_7_8_p36_example12a[16] = { + 1, 3, 5, 7, 9, [16-5] = 8, 6, 4, 2, 0 +}; + +int c99_6_7_8_p36_example12b[8] = { + 1, 3, 5, 7, 9, [8-5] = 8, 6, 4, 2, 0 +}; + +union { + int first_member; + void *second_member; + unsigned char any_member; +} c99_6_7_8_p38_example13 = { .any_member = 42 }; + + +/* + * During initialization of an object of type array of unknown size, the type + * information on the symbol is updated in-place. Ensure that this happens on + * a copy of the type. + * + * C99 6.7.8p31 example 7 + */ +void +ensure_array_type_is_not_modified_during_initialization(void) +{ + typedef int array_of_unknown_size[]; + + array_of_unknown_size a1 = { 1, 2, 3}; + + switch (4) { + case sizeof(array_of_unknown_size): + /* expect+1: error: duplicate case '0' in switch [199] */ + case 0: + case 3: + case 4: + case 12: + break; + } + + /* expect+1: error: negative array dimension (-12) [20] */ + typedef int reveal_sizeof_a1[-(int)(sizeof(a1))]; +} + +struct point unknown_member_name_beginning = { + /* expect+1: error: type 'struct point' does not have member 'r' [101] */ + .r = 5, + .x = 4, + .y = 3, +}; + +struct point unknown_member_name_middle = { + .x = 4, + /* expect+1: error: type 'struct point' does not have member 'r' [101] */ + .r = 5, + .y = 3, +}; + +struct point unknown_member_name_end = { + .x = 4, + .y = 3, + /* expect+1: error: type 'struct point' does not have member 'r' [101] */ + .r = 5, +}; + +union value { + int int_value; + void *pointer_value; +}; + +union value unknown_union_member_name_first = { + /* expect+1: error: type 'union value' does not have member 'unknown_value' [101] */ + .unknown_value = 4, + .int_value = 3, +}; + +union value unknown_union_member_name_second = { + .int_value = 3, + /* expect+1: error: type 'union value' does not have member 'unknown_value' [101] */ + .unknown_value = 4, +}; + +struct point subscript_designator_on_struct = { + /* expect+1: error: syntax error 'designator '[...]' is only for arrays' [249] */ + [0] = 3, +}; + +struct point unknown_member_on_struct = { + /* expect+1: error: type 'struct point' does not have member 'member' [101] */ + .member[0][0].member = 4, +}; + +struct point unknown_member_on_scalar = { + /* expect+1: error: syntax error 'scalar type cannot use designator' [249] */ + .x.y.z = 5, +}; + +struct { + int:16; + /* expect+2: warning: 'struct <unnamed>' has no named members [65] */ + /* expect+1: error: cannot initialize struct/union with no named member [179] */ +} struct_with_only_unnamed_members = { + 123, +}; + +union { + int:16; + /* expect+2: warning: 'union <unnamed>' has no named members [65] */ + /* expect+1: error: cannot initialize struct/union with no named member [179] */ +} union_with_only_unnamed_members = { + 123, +}; + +int designator_for_scalar = { + /* expect+1: error: syntax error 'scalar type cannot use designator' [249] */ + .value = 3, +}; + +struct point member_designator_for_scalar_in_struct = { + /* expect+1: error: syntax error 'scalar type cannot use designator' [249] */ + { .x = 3 }, +}; +struct point subscript_designator_for_scalar_in_struct = { + /* expect+1: error: syntax error 'designator '[...]' is only for arrays' [249] */ + { [1] = 4 }, +}; + + +/* Seen in pcidevs_data.h, variable 'pci_words'. */ +const char string_initialized_with_braced_literal[] = { + "initializer", +}; + +// An array of unknown size containing strings. +char weekday_names[][4] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +/* nested struct/union initialization */ +struct outer { + int i; + char c; + union inner { + short us; + char uc; + } u; + char *s; +} struct_containing_union[] = { + { + .s = "foo", + .c = 'b', + .u = { + .uc = 'c' + } + }, + { + .i = 1, + .c = 'a', + .u = { + .us = 2 + } + }, +}; + +/* + * The expansion of the offsetof macro may dereference a null pointer. + * Such expressions are allowed in initializers for objects with + * static duration. + */ +struct offset_and_data { + unsigned long offset; + unsigned long data; +}; + +struct offset_and_data offset_and_data = { + (unsigned long)&(((struct offset_and_data *)0)->data), + 0, +}; + +// The size of the array is determined by the maximum index, not by the last +// one mentioned. +int arr_11[] = { [10] = 10, [0] = 0 }; +/* expect+1: error: negative array dimension (-11) [20] */ +typedef int ctassert_11[-(int)(sizeof(arr_11) / sizeof(arr_11[0]))]; + +// Without an explicit subscript designator, the subscript counts up. +int arr_3[] = { [1] = 1, [0] = 0, 1, 2 }; +/* expect+1: error: negative array dimension (-3) [20] */ +typedef int ctassert_3[-(int)(sizeof(arr_3) / sizeof(arr_3[0]))]; + + +// C99 struct initialization using designators. +struct { + int i; + char *s; +} struct_array[] = { + { + .i = 2, + }, + { + .s = "foo" + }, + { + .i = 1, + .s = "bar" + }, + { + .s = "foo", + .i = -1 + }, +}; + +// Ensure that deeply nested structs can be designated in an initializer. +int +init_deeply_nested_struct(void) +{ + struct rgb { + unsigned red; + unsigned green; + unsigned blue; + }; + + struct hobbies { + unsigned dancing: 1; + unsigned running: 1; + unsigned swimming: 1; + }; + + struct person { + struct hobbies hobbies; + struct rgb favorite_color; + }; + + struct city { + struct person mayor; + }; + + struct state { + struct city capital; + }; + + struct state st = { + .capital.mayor.hobbies.dancing = 1, + .capital.mayor.favorite_color.green = 0xFF, + .capital.mayor.favorite_color.red = 0xFF, + }; + return st.capital.mayor.favorite_color.red; +} + +struct { + int i[10]; + char *s; +} struct_array_with_inner_array[] = { + { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + "foo" + }, +}; + +struct { + int type; + union { + char b[20]; + short s[10]; + long l[5]; + } data; +} array_in_union_in_struct = { + .type = 3, + .data.l[0] = 4 +}; + +// Somewhere between 2005.12.24.20.47.56 and 2006.12.19.19.06.44, lint could +// not initialize named members, see PR bin/20264. +union { + char *p; + int a[1]; +} array_in_union = { + .a = { 7 } +}; + +/* + * Initialization of a nested struct, in which some parts are initialized + * from non-constant expressions of the inner struct type. + * + * In C99, 6.7.8p13 describes exactly this case. + */ +void +init_nested_struct(void) +{ + + typedef enum O1 { + O1C = 101 + } O1; + typedef enum O2 { + O2C = 102 + } O2; + typedef enum O3 { + O3C = 103 + } O3; + typedef enum I1 { + I1C = 201 + } I1; + typedef enum I2 { + I2C = 202 + } I2; + + struct Inner1 { + I1 i1; + }; + + struct Outer3Inner1 { + O1 o1; + struct Inner1 inner; + O3 o3; + }; + + struct Inner1 inner1 = { + I1C + }; + struct Outer3Inner1 o3i1 = { + O1C, + inner1, + O3C + }; + + O1 o1 = o3i1.o1; + + struct Inner2 { + I1 i1; + I2 i2; + }; + + struct Outer3Inner2 { + O1 o1; + struct Inner2 inner; + O3 o3; + }; + + struct Inner2 inner2 = { + I1C, + I2C + }; + struct Outer3Inner2 o3i2 = { + O1C, + inner2, + O3C + }; + o1 = o3i2.o1; + + /* + * For static storage duration, each initializer expression must be a + * constant expression. + */ + static struct Inner2 inner3_static = { + I1C, + I2C + }; + static struct Outer3Inner2 o3i2_static = { + O1C, + /* expect+1: error: non-constant initializer [177] */ + inner3_static, + O3C + }; +}