Module Name: src Committed By: rillig Date: Sun Dec 8 17:12:01 UTC 2024
Modified Files: src/distrib/sets/lists/tests: mi src/tests/usr.bin/xlint/lint1: msg_255.c t_usage.sh src/usr.bin/xlint/common: externs.h tyname.c src/usr.bin/xlint/lint1: err.c externs1.h lex.c scan.l src/usr.bin/xlint/xlint: xlint.c Added Files: src/tests/usr.bin/xlint/lint1: msg_385.c Log Message: lint: warn about do-while macros that end with a semicolon To generate a diff of this commit: cvs rdiff -u -r1.1348 -r1.1349 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.6 -r1.7 src/tests/usr.bin/xlint/lint1/msg_255.c cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/msg_385.c cvs rdiff -u -r1.26 -r1.27 src/tests/usr.bin/xlint/lint1/t_usage.sh cvs rdiff -u -r1.36 -r1.37 src/usr.bin/xlint/common/externs.h cvs rdiff -u -r1.64 -r1.65 src/usr.bin/xlint/common/tyname.c cvs rdiff -u -r1.259 -r1.260 src/usr.bin/xlint/lint1/err.c cvs rdiff -u -r1.237 -r1.238 src/usr.bin/xlint/lint1/externs1.h cvs rdiff -u -r1.231 -r1.232 src/usr.bin/xlint/lint1/lex.c cvs rdiff -u -r1.142 -r1.143 src/usr.bin/xlint/lint1/scan.l cvs rdiff -u -r1.125 -r1.126 src/usr.bin/xlint/xlint/xlint.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.1348 src/distrib/sets/lists/tests/mi:1.1349 --- src/distrib/sets/lists/tests/mi:1.1348 Sun Dec 1 18:37:53 2024 +++ src/distrib/sets/lists/tests/mi Sun Dec 8 17:12:00 2024 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1348 2024/12/01 18:37:53 rillig Exp $ +# $NetBSD: mi,v 1.1349 2024/12/08 17:12:00 rillig Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -7591,6 +7591,7 @@ ./usr/tests/usr.bin/xlint/lint1/msg_382.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/msg_383.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/msg_384.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/msg_385.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/op_colon.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/op_colon.exp tests-obsolete obsolete,atf ./usr/tests/usr.bin/xlint/lint1/op_shl_lp64.c tests-usr.bin-tests compattestfile,atf Index: src/tests/usr.bin/xlint/lint1/msg_255.c diff -u src/tests/usr.bin/xlint/lint1/msg_255.c:1.6 src/tests/usr.bin/xlint/lint1/msg_255.c:1.7 --- src/tests/usr.bin/xlint/lint1/msg_255.c:1.6 Fri Aug 11 04:27:49 2023 +++ src/tests/usr.bin/xlint/lint1/msg_255.c Sun Dec 8 17:12:01 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: msg_255.c,v 1.6 2023/08/11 04:27:49 rillig Exp $ */ +/* $NetBSD: msg_255.c,v 1.7 2024/12/08 17:12:01 rillig Exp $ */ # 3 "msg_255.c" // Test for message: undefined or invalid '#' directive [255] @@ -34,12 +34,13 @@ /* expect+1: warning: undefined or invalid '#' directive [255] */ # 4 / -/* expect+1: warning: undefined or invalid '#' directive [255] */ +/* expect+3: error: newline in string or char constant [254] */ +/* expect+2: error: unterminated string constant [258] */ # 5 "unfinished // An empty string means standard input; tabs may be used for spacing. # 6 "" -# 44 "msg_255.c" +# 45 "msg_255.c" int dummy; Index: src/tests/usr.bin/xlint/lint1/t_usage.sh diff -u src/tests/usr.bin/xlint/lint1/t_usage.sh:1.26 src/tests/usr.bin/xlint/lint1/t_usage.sh:1.27 --- src/tests/usr.bin/xlint/lint1/t_usage.sh:1.26 Sun Dec 1 18:37:54 2024 +++ src/tests/usr.bin/xlint/lint1/t_usage.sh Sun Dec 8 17:12:01 2024 @@ -1,4 +1,4 @@ -# $NetBSD: t_usage.sh,v 1.26 2024/12/01 18:37:54 rillig Exp $ +# $NetBSD: t_usage.sh,v 1.27 2024/12/08 17:12:01 rillig Exp $ # # Copyright (c) 2023 The NetBSD Foundation, Inc. # All rights reserved. @@ -39,13 +39,13 @@ suppress_messages_body() # The largest known message. atf_check \ - "$lint1" -X 384 code.c /dev/null + "$lint1" -X 385 code.c /dev/null # Larger than the largest known message. atf_check \ -s 'exit:1' \ - -e "inline:lint1: invalid message ID '385'\n" \ - "$lint1" -X 385 code.c /dev/null + -e "inline:lint1: invalid message ID '386'\n" \ + "$lint1" -X 386 code.c /dev/null # Whitespace is not allowed before a message ID. atf_check \ Index: src/usr.bin/xlint/common/externs.h diff -u src/usr.bin/xlint/common/externs.h:1.36 src/usr.bin/xlint/common/externs.h:1.37 --- src/usr.bin/xlint/common/externs.h:1.36 Fri Feb 2 16:25:58 2024 +++ src/usr.bin/xlint/common/externs.h Sun Dec 8 17:12:00 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: externs.h,v 1.36 2024/02/02 16:25:58 rillig Exp $ */ +/* $NetBSD: externs.h,v 1.37 2024/12/08 17:12:00 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -41,6 +41,7 @@ const char *tspec_name(tspec_t); #if IS_LINT1 void buf_init(buffer *); void buf_add_char(buffer *, char); +void buf_add(buffer *, const char *); #endif /* Index: src/usr.bin/xlint/common/tyname.c diff -u src/usr.bin/xlint/common/tyname.c:1.64 src/usr.bin/xlint/common/tyname.c:1.65 --- src/usr.bin/xlint/common/tyname.c:1.64 Sat Nov 30 16:34:26 2024 +++ src/usr.bin/xlint/common/tyname.c Sun Dec 8 17:12:00 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: tyname.c,v 1.64 2024/11/30 16:34:26 rillig Exp $ */ +/* $NetBSD: tyname.c,v 1.65 2024/12/08 17:12:00 rillig Exp $ */ /*- * Copyright (c) 2005 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: tyname.c,v 1.64 2024/11/30 16:34:26 rillig Exp $"); +__RCSID("$NetBSD: tyname.c,v 1.65 2024/12/08 17:12:00 rillig Exp $"); #endif #include <assert.h> @@ -94,11 +94,10 @@ intern(const char *name) return n->ntn_name; } -#if IS_LINT1 -void -#else -static void +#if !IS_LINT1 +static #endif +void buf_init(buffer *buf) { buf->len = 0; @@ -134,7 +133,10 @@ buf_add_char(buffer *buf, char c) } #endif -static void +#if !IS_LINT1 +static +#endif +void buf_add(buffer *buf, const char *s) { buf_add_mem(buf, s, strlen(s)); Index: src/usr.bin/xlint/lint1/err.c diff -u src/usr.bin/xlint/lint1/err.c:1.259 src/usr.bin/xlint/lint1/err.c:1.260 --- src/usr.bin/xlint/lint1/err.c:1.259 Sun Dec 1 18:37:54 2024 +++ src/usr.bin/xlint/lint1/err.c Sun Dec 8 17:12:01 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: err.c,v 1.259 2024/12/01 18:37:54 rillig Exp $ */ +/* $NetBSD: err.c,v 1.260 2024/12/08 17:12:01 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: err.c,v 1.259 2024/12/01 18:37:54 rillig Exp $"); +__RCSID("$NetBSD: err.c,v 1.260 2024/12/08 17:12:01 rillig Exp $"); #endif #include <limits.h> @@ -440,6 +440,7 @@ static const char *const msgs[] = { "constant assignment of type '%s' in operand of '!' always evaluates to '%s'", // 382 "passing '%s' to argument %d discards '%s'", // 383 "function definition with identifier list is obsolete in C23", // 384 + "do-while macro '%.*s' ends with semicolon", // 385 }; static bool is_suppressed[sizeof(msgs) / sizeof(msgs[0])]; Index: src/usr.bin/xlint/lint1/externs1.h diff -u src/usr.bin/xlint/lint1/externs1.h:1.237 src/usr.bin/xlint/lint1/externs1.h:1.238 --- src/usr.bin/xlint/lint1/externs1.h:1.237 Sat Nov 30 10:43:49 2024 +++ src/usr.bin/xlint/lint1/externs1.h Sun Dec 8 17:12:01 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: externs1.h,v 1.237 2024/11/30 10:43:49 rillig Exp $ */ +/* $NetBSD: externs1.h,v 1.238 2024/12/08 17:12:01 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -391,6 +391,15 @@ void outusg(const sym_t *); /* * lex.c */ +void lex_pp_begin(void); +void lex_pp_identifier(const char *); +void lex_pp_number(const char *); +void lex_pp_character_constant(void); +void lex_pp_string_literal(void); +void lex_pp_punctuator(const char *); +void lex_pp_comment(void); +void lex_pp_whitespace(void); +void lex_pp_end(void); int lex_name(const char *, size_t); int lex_integer_constant(const char *, size_t, int); int lex_floating_constant(const char *, size_t); @@ -399,7 +408,6 @@ int lex_string(void); int lex_wide_string(void); int lex_character_constant(void); int lex_wide_character_constant(void); -void lex_directive(const char *); void lex_next_line(void); void lex_comment(void); void lex_slash_slash_comment(void); Index: src/usr.bin/xlint/lint1/lex.c diff -u src/usr.bin/xlint/lint1/lex.c:1.231 src/usr.bin/xlint/lint1/lex.c:1.232 --- src/usr.bin/xlint/lint1/lex.c:1.231 Fri Nov 29 20:02:35 2024 +++ src/usr.bin/xlint/lint1/lex.c Sun Dec 8 17:12:01 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: lex.c,v 1.231 2024/11/29 20:02:35 rillig Exp $ */ +/* $NetBSD: lex.c,v 1.232 2024/12/08 17:12:01 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.231 2024/11/29 20:02:35 rillig Exp $"); +__RCSID("$NetBSD: lex.c,v 1.232 2024/12/08 17:12:01 rillig Exp $"); #endif #include <ctype.h> @@ -689,20 +689,20 @@ lex_operator(int t, op_t o) return t; } -static buffer * +static buffer read_quoted(bool *complete, char delim, bool wide) { - buffer *buf = xcalloc(1, sizeof(*buf)); - buf_init(buf); + buffer buf; + buf_init(&buf); if (wide) - buf_add_char(buf, 'L'); - buf_add_char(buf, delim); + buf_add_char(&buf, 'L'); + buf_add_char(&buf, delim); for (;;) { int c = read_byte(); if (c <= 0) break; - buf_add_char(buf, (char)c); + buf_add_char(&buf, (char)c); if (c == '\n') break; if (c == delim) { @@ -711,13 +711,13 @@ read_quoted(bool *complete, char delim, } if (c == '\\') { c = read_byte(); - buf_add_char(buf, (char)(c <= 0 ? ' ' : c)); + buf_add_char(&buf, (char)(c <= 0 ? ' ' : c)); if (c <= 0) break; } } *complete = false; - buf_add_char(buf, delim); + buf_add_char(&buf, delim); return buf; } @@ -931,12 +931,12 @@ check_quoted(const buffer *buf, bool com error(253); } -static buffer * +static buffer lex_quoted(char delim, bool wide) { bool complete; - buffer *buf = read_quoted(&complete, delim, wide); - check_quoted(buf, complete, delim); + buffer buf = read_quoted(&complete, delim, wide); + check_quoted(&buf, complete, delim); return buf; } @@ -944,12 +944,12 @@ lex_quoted(char delim, bool wide) int lex_character_constant(void) { - buffer *buf = lex_quoted('\'', false); + buffer buf = lex_quoted('\'', false); size_t n = 0; uint64_t val = 0; quoted_iterator it = { .end = 0 }; - while (quoted_next(buf, &it)) { + while (quoted_next(&buf, &it)) { val = (val << CHAR_SIZE) + it.value; n++; } @@ -983,13 +983,13 @@ lex_character_constant(void) int lex_wide_character_constant(void) { - buffer *buf = lex_quoted('\'', true); + buffer buf = lex_quoted('\'', true); static char wbuf[MB_LEN_MAX + 1]; size_t n = 0, nmax = MB_CUR_MAX; quoted_iterator it = { .end = 0 }; - while (quoted_next(buf, &it)) { + while (quoted_next(&buf, &it)) { if (n < nmax) wbuf[n] = (char)it.value; n++; @@ -1064,36 +1064,19 @@ set_csrc_pos(void) outsrc(transform_filename(curr_pos.p_file, strlen(curr_pos.p_file))); } -/* - * Called for preprocessor directives. Currently implemented are: - * # pragma [argument...] - * # lineno - * # lineno "filename" [GCC-flag...] - */ -void -lex_directive(const char *text) +/* # lineno ["filename" [GCC-flag...]] */ +static void +set_location(const char *p) { - const char *p = text + 1; /* skip '#' */ - - while (*p == ' ' || *p == '\t') - p++; - - if (!ch_isdigit(*p)) { - if (strncmp(p, "pragma", 6) == 0 - && ch_isspace(p[6])) - return; - goto error; - } - char *end; long ln = strtol(--p, &end, 10); if (end == p) goto error; p = end; - if (*p != ' ' && *p != '\t' && *p != '\0') + if (*p != ' ' && *p != '\0') goto error; - while (*p == ' ' || *p == '\t') + while (*p == ' ') p++; if (*p != '\0') { @@ -1132,6 +1115,141 @@ error: warning(255); } +static void +check_stmt_macro(const char *text) +{ + const char *p = text; + while (*p == ' ') + p++; + + const char *name_start = p; + while (ch_isalnum(*p) || *p == '_') + p++; + const char *name_end = p; + + if (*p == '(') { + while (*p != '\0' && *p != ')') + p++; + if (*p == ')') + p++; + } + + while (*p == ' ') + p++; + + if (strncmp(p, "do", 2) == 0 && !ch_isalnum(p[2])) + /* do-while macro '%.*s' ends with semicolon */ + warning(385, (int)(name_end - name_start), name_start); +} + +// Between lex_pp_begin and lex_pp_end, the current preprocessing line, +// with comments and whitespace converted to a single space. +static buffer pp_line; + +void +lex_pp_begin(void) +{ + if (pp_line.data == NULL) + buf_init(&pp_line); + debug_step("%s", __func__); + lint_assert(pp_line.len == 0); +} + +void +lex_pp_identifier(const char *text) +{ + debug_step("%s '%s'", __func__, text); + buf_add(&pp_line, text); +} + +void +lex_pp_number(const char *text) +{ + debug_step("%s '%s'", __func__, text); + buf_add(&pp_line, text); +} + +void +lex_pp_character_constant(void) +{ + buffer buf = lex_quoted('\'', false); + debug_step("%s '%s'", __func__, buf.data); + buf_add(&pp_line, buf.data); + free(buf.data); +} + +void +lex_pp_string_literal(void) +{ + buffer buf = lex_quoted('"', false); + debug_step("%s '%s'", __func__, buf.data); + buf_add(&pp_line, buf.data); + free(buf.data); +} + +void +lex_pp_punctuator(const char *text) +{ + debug_step("%s '%s'", __func__, text); + buf_add(&pp_line, text); +} + +void +lex_pp_comment(void) +{ + int lc = -1, c; + + for (;;) { + if ((c = read_byte()) == EOF) { + /* unterminated comment */ + error(256); + return; + } + if (lc == '*' && c == '/') + break; + lc = c; + } + + buf_add_char(&pp_line, ' '); +} + +void +lex_pp_whitespace(void) +{ + buf_add_char(&pp_line, ' '); +} + +void +lex_pp_end(void) +{ + const char *text = pp_line.data; + size_t len = pp_line.len; + while (len > 0 && text[len - 1] == ' ') + len--; + debug_step("%s '%.*s'", __func__, (int)len, text); + + const char *p = text; + while (*p == ' ') + p++; + + if (ch_isdigit(*p)) + set_location(p); + else if (strncmp(p, "pragma ", 7) == 0) + goto done; + else if (strncmp(p, "define ", 7) == 0) { + if (text[len - 1] == ';') + check_stmt_macro(p + 7); + } else if (strncmp(p, "undef ", 6) == 0) + goto done; + else + /* undefined or invalid '#' directive */ + warning(255); + +done: + pp_line.len = 0; + pp_line.data[0] = '\0'; +} + /* Handle lint comments such as ARGSUSED. */ void lex_comment(void) @@ -1251,7 +1369,9 @@ reset_suppressions(void) int lex_string(void) { - yylval.y_string = lex_quoted('"', false); + buffer *buf = xmalloc(sizeof(*buf)); + *buf = lex_quoted('"', false); + yylval.y_string = buf; return T_STRING; } @@ -1277,18 +1397,19 @@ wide_length(const buffer *buf) int lex_wide_string(void) { - buffer *buf = lex_quoted('"', true); + buffer buf = lex_quoted('"', true); buffer str; buf_init(&str); quoted_iterator it = { .end = 0 }; - while (quoted_next(buf, &it)) + while (quoted_next(&buf, &it)) buf_add_char(&str, (char)it.value); - free(buf->data); - *buf = (buffer) { .len = wide_length(&str) }; + free(buf.data); - yylval.y_string = buf; + buffer *len_buf = xcalloc(1, sizeof(*len_buf)); + len_buf->len = wide_length(&str); + yylval.y_string = len_buf; return T_STRING; } Index: src/usr.bin/xlint/lint1/scan.l diff -u src/usr.bin/xlint/lint1/scan.l:1.142 src/usr.bin/xlint/lint1/scan.l:1.143 --- src/usr.bin/xlint/lint1/scan.l:1.142 Sun May 12 08:48:36 2024 +++ src/usr.bin/xlint/lint1/scan.l Sun Dec 8 17:12:01 2024 @@ -1,5 +1,5 @@ %{ -/* $NetBSD: scan.l,v 1.142 2024/05/12 08:48:36 rillig Exp $ */ +/* $NetBSD: scan.l,v 1.143 2024/12/08 17:12:01 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -35,7 +35,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: scan.l,v 1.142 2024/05/12 08:48:36 rillig Exp $"); +__RCSID("$NetBSD: scan.l,v 1.143 2024/12/08 17:12:01 rillig Exp $"); #endif #include "lint1.h" @@ -49,9 +49,20 @@ EXP ([eE][+-]?[0-9]+) PEXP (p[+-]?[0-9A-Fa-f]+) FSUF ([fFlL]?[i]?) +punctuator_1 [\[\](){}.]|-> +punctuator_2 {punctuator_1}|\+\+|--|[&*+\-~!] +punctuator_3 {punctuator_2}|\/|%|<<|>>|<|>|<=|>=|==|!=|\^|\||&&|\|\| +punctuator_4 {punctuator_3}|\?|:|::|;|\.\.\. +punctuator_5 {punctuator_4}|=|\*=|\/=|%=|\+=|-=|<<=|>>=|&=|\^=|\|= +punctuator_6 {punctuator_5}|,|#|## +punctuator_7 {punctuator_6}|<:|:>|<%|%>|%:|%:%: +punctuator {punctuator_7}|@ + %pointer %option nounput +%x preprocessing + %% [_A-Za-z][_A-Za-z0-9]* return lex_name(yytext, yyleng); @@ -115,11 +126,29 @@ FSUF ([fFlL]?[i]?) "::" return T_DCOLON; "'" return lex_character_constant(); "L'" return lex_wide_character_constant(); -^#.*$ lex_directive(yytext); \n lex_next_line(); \t|" "|\f|\v ; "/*" lex_comment(); "//" lex_slash_slash_comment(); + +^# { + BEGIN preprocessing; + lex_pp_begin(); + } +<preprocessing>[_A-Za-z][_A-Za-z0-9]* lex_pp_identifier(yytext); +<preprocessing>\.?[0-9]('?[_A-Za-z0-9]|[EePp][-+][0-9]+|\.)* lex_pp_number(yytext); +<preprocessing>\' lex_pp_character_constant(); +<preprocessing>\" lex_pp_string_literal(); +<preprocessing>{punctuator} lex_pp_punctuator(yytext); +<preprocessing>\/\* lex_pp_comment(); +<preprocessing>[ \f\t\v]+ lex_pp_whitespace(); +<preprocessing>. lex_unknown_character(yytext[0]); +<preprocessing>\n { + lex_pp_end(); + lex_next_line(); + BEGIN INITIAL; + } + . lex_unknown_character(yytext[0]); %% Index: src/usr.bin/xlint/xlint/xlint.c diff -u src/usr.bin/xlint/xlint/xlint.c:1.125 src/usr.bin/xlint/xlint/xlint.c:1.126 --- src/usr.bin/xlint/xlint/xlint.c:1.125 Sun May 12 18:49:36 2024 +++ src/usr.bin/xlint/xlint/xlint.c Sun Dec 8 17:12:01 2024 @@ -1,4 +1,4 @@ -/* $NetBSD: xlint.c,v 1.125 2024/05/12 18:49:36 rillig Exp $ */ +/* $NetBSD: xlint.c,v 1.126 2024/12/08 17:12:01 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) -__RCSID("$NetBSD: xlint.c,v 1.125 2024/05/12 18:49:36 rillig Exp $"); +__RCSID("$NetBSD: xlint.c,v 1.126 2024/12/08 17:12:01 rillig Exp $"); #endif #include <sys/param.h> @@ -579,6 +579,7 @@ main(int argc, char *argv[]) list_add(&cpp.flags, "-Dlint"); /* XXX don't define with -s */ list_add(&cpp.flags, "-D__lint"); list_add(&cpp.flags, "-D__lint__"); + list_add(&cpp.flags, "-dD"); list_add(&default_libraries, "c"); Added files: Index: src/tests/usr.bin/xlint/lint1/msg_385.c diff -u /dev/null src/tests/usr.bin/xlint/lint1/msg_385.c:1.1 --- /dev/null Sun Dec 8 17:12:01 2024 +++ src/tests/usr.bin/xlint/lint1/msg_385.c Sun Dec 8 17:12:01 2024 @@ -0,0 +1,54 @@ +/* $NetBSD: msg_385.c,v 1.1 2024/12/08 17:12:01 rillig Exp $ */ +# 3 "msg_385.c" + +// Test for message: do-while macro '%.*s' ends with semicolon [385] + +/* + * A function-like macro that consists of a do-while statement is intended to + * expand to a single statement, but without the trailing semicolon, as the + * semicolon is already provided by the calling site. When the macro expansion + * ends with a semicolon, there are two semicolons, which can lead to syntax + * errors. + */ + +/* lint1-extra-flags: -X 351 */ + +/* expect+1: warning: do-while macro 'wrong_stmt' ends with semicolon [385] */ +#define wrong_stmt() do { } while (0); + +#define correct_stmt() do { } while (0) + +/* expect+5: warning: do-while macro 'wrong_stmt_with_comment' ends with semicolon [385] */ +#define wrong_stmt_with_comment() do { } while (0); /* +a +b +c +*/ + +#define correct_stmt_with_comment() do { } while (0) /* +a +b +c +*/ + +/* The comment marker inside the string literal does not start a comment. */ +#define stmt_with_string() do { print("/*"); } while (0) + +void +call_wrong_stmt(int x) +{ + if (x > 0) + do { } while (0);; + /* expect+1: error: syntax error 'else' [249] */ + else + do { } while (0);; +} + +void +call_correct_stmt(int x) +{ + if (x < 0) + do { } while (0); + else + do { } while (0); +}