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);
+}