Module Name:    src
Committed By:   rillig
Date:           Thu Dec 31 18:51:28 UTC 2020

Modified Files:
        src/distrib/sets/lists/tests: mi
        src/tests/usr.bin/xlint/lint1: Makefile t_integration.sh
        src/usr.bin/xlint/common: tyname.c
        src/usr.bin/xlint/lint1: func.c
Added Files:
        src/tests/usr.bin/xlint/lint1: d_fold_test.c d_fold_test.exp

Log Message:
lint: check that in "if (cond)", cond is scalar


To generate a diff of this commit:
cvs rdiff -u -r1.1003 -r1.1004 src/distrib/sets/lists/tests/mi
cvs rdiff -u -r1.21 -r1.22 src/tests/usr.bin/xlint/lint1/Makefile
cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/d_fold_test.c \
    src/tests/usr.bin/xlint/lint1/d_fold_test.exp
cvs rdiff -u -r1.14 -r1.15 src/tests/usr.bin/xlint/lint1/t_integration.sh
cvs rdiff -u -r1.16 -r1.17 src/usr.bin/xlint/common/tyname.c
cvs rdiff -u -r1.38 -r1.39 src/usr.bin/xlint/lint1/func.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.1003 src/distrib/sets/lists/tests/mi:1.1004
--- src/distrib/sets/lists/tests/mi:1.1003	Thu Dec 31 03:05:12 2020
+++ src/distrib/sets/lists/tests/mi	Thu Dec 31 18:51:28 2020
@@ -1,4 +1,4 @@
-# $NetBSD: mi,v 1.1003 2020/12/31 03:05:12 rillig Exp $
+# $NetBSD: mi,v 1.1004 2020/12/31 18:51:28 rillig Exp $
 #
 # Note: don't delete entries from here - mark them as "obsolete" instead.
 #
@@ -5782,6 +5782,8 @@
 ./usr/tests/usr.bin/xlint/lint1/d_decl_old_style_arguments.c	tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_decl_old_style_arguments.exp	tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_ellipsis_in_switch.c		tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/d_fold_test.c			tests-usr.bin-tests	compattestfile,atf
+./usr/tests/usr.bin/xlint/lint1/d_fold_test.exp			tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements1.c	tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements2.c	tests-usr.bin-tests	compattestfile,atf
 ./usr/tests/usr.bin/xlint/lint1/d_gcc_compound_statements3.c	tests-usr.bin-tests	compattestfile,atf

Index: src/tests/usr.bin/xlint/lint1/Makefile
diff -u src/tests/usr.bin/xlint/lint1/Makefile:1.21 src/tests/usr.bin/xlint/lint1/Makefile:1.22
--- src/tests/usr.bin/xlint/lint1/Makefile:1.21	Wed Dec 30 13:15:07 2020
+++ src/tests/usr.bin/xlint/lint1/Makefile	Thu Dec 31 18:51:28 2020
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.21 2020/12/30 13:15:07 rillig Exp $
+# $NetBSD: Makefile,v 1.22 2020/12/31 18:51:28 rillig Exp $
 
 NOMAN=		# defined
 
@@ -50,6 +50,8 @@ FILES+=		d_cvt_in_ternary.c
 FILES+=		d_decl_old_style_arguments.c
 FILES+=		d_decl_old_style_arguments.exp
 FILES+=		d_ellipsis_in_switch.c
+FILES+=		d_fold_test.c
+FILES+=		d_fold_test.exp
 FILES+=		d_gcc_compound_statements1.c
 FILES+=		d_gcc_compound_statements2.c
 FILES+=		d_gcc_compound_statements3.c

Index: src/tests/usr.bin/xlint/lint1/t_integration.sh
diff -u src/tests/usr.bin/xlint/lint1/t_integration.sh:1.14 src/tests/usr.bin/xlint/lint1/t_integration.sh:1.15
--- src/tests/usr.bin/xlint/lint1/t_integration.sh:1.14	Wed Dec 30 13:42:19 2020
+++ src/tests/usr.bin/xlint/lint1/t_integration.sh	Thu Dec 31 18:51:28 2020
@@ -1,4 +1,4 @@
-# $NetBSD: t_integration.sh,v 1.14 2020/12/30 13:42:19 rillig Exp $
+# $NetBSD: t_integration.sh,v 1.15 2020/12/31 18:51:28 rillig Exp $
 #
 # Copyright (c) 2008, 2010 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -74,6 +74,7 @@ test_case c99_union_init4
 test_case cast_fun_array_param
 test_case cast_typeof
 test_case decl_old_style_arguments
+test_case fold_test
 test_case gcc_extension
 test_case type_question_colon
 test_case typefun

Index: src/usr.bin/xlint/common/tyname.c
diff -u src/usr.bin/xlint/common/tyname.c:1.16 src/usr.bin/xlint/common/tyname.c:1.17
--- src/usr.bin/xlint/common/tyname.c:1.16	Tue Dec 29 13:33:03 2020
+++ src/usr.bin/xlint/common/tyname.c	Thu Dec 31 18:51:28 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: tyname.c,v 1.16 2020/12/29 13:33:03 rillig Exp $	*/
+/*	$NetBSD: tyname.c,v 1.17 2020/12/31 18:51:28 rillig Exp $	*/
 
 /*-
  * Copyright (c) 2005 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: tyname.c,v 1.16 2020/12/29 13:33:03 rillig Exp $");
+__RCSID("$NetBSD: tyname.c,v 1.17 2020/12/31 18:51:28 rillig Exp $");
 #endif
 
 #include <limits.h>
@@ -87,6 +87,8 @@ basic_type_name(tspec_t t)
 	case DCOMPLEX:	return "double _Complex";
 	case LCOMPLEX:	return "long double _Complex";
 	case COMPLEX:	return "_Complex";
+	case SIGNED:	return "signed";
+	case UNSIGN:	return "unsigned";
 	default:
 		LERROR("basic_type_name(%d)", t);
 		return NULL;
@@ -204,6 +206,8 @@ tyname(char *buf, size_t bufsiz, const t
 	case FCOMPLEX:
 	case DCOMPLEX:
 	case LCOMPLEX:
+	case SIGNED:
+	case UNSIGN:
 		(void)snprintf(buf, bufsiz, "%s%s", cv, s);
 		break;
 	case PTR:

Index: src/usr.bin/xlint/lint1/func.c
diff -u src/usr.bin/xlint/lint1/func.c:1.38 src/usr.bin/xlint/lint1/func.c:1.39
--- src/usr.bin/xlint/lint1/func.c:1.38	Wed Dec 30 13:17:42 2020
+++ src/usr.bin/xlint/lint1/func.c	Thu Dec 31 18:51:28 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: func.c,v 1.38 2020/12/30 13:17:42 rillig Exp $	*/
+/*	$NetBSD: func.c,v 1.39 2020/12/31 18:51:28 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: func.c,v 1.38 2020/12/30 13:17:42 rillig Exp $");
+__RCSID("$NetBSD: func.c,v 1.39 2020/12/31 18:51:28 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -527,6 +527,28 @@ label(int typ, sym_t *sym, tnode_t *tn)
 	reached = 1;
 }
 
+static tnode_t *
+check_controlling_expression(tnode_t *tn)
+{
+	tspec_t t = tn->tn_type->t_tspec;
+
+	if (tn != NULL)
+		tn = cconv(tn);
+	if (tn != NULL)
+		tn = promote(NOOP, 0, tn);
+
+	if (tn != NULL && !tspec_is_scalar(t)) {
+		/* C99 6.5.15p4 for the ?: operator; see typeok:QUEST */
+		/* C99 6.8.4.1p1 for if statements */
+		/* C99 6.8.5p2 for while, do and for loops */
+		/* controlling expressions must have scalar type */
+		error(204);
+		return NULL;
+	}
+
+	return tn;
+}
+
 /*
  * T_IF T_LPARN expr T_RPARN
  */
@@ -535,10 +557,9 @@ if1(tnode_t *tn)
 {
 
 	if (tn != NULL)
-		tn = cconv(tn);
+		tn = check_controlling_expression(tn);
 	if (tn != NULL)
-		tn = promote(NOOP, 0, tn);
-	expr(tn, 0, 1, 0);
+		expr(tn, 0, 1, 0);
 	pushctrl(T_IF);
 }
 
@@ -690,14 +711,7 @@ while1(tnode_t *tn)
 	}
 
 	if (tn != NULL)
-		tn = cconv(tn);
-	if (tn != NULL)
-		tn = promote(NOOP, 0, tn);
-	if (tn != NULL && !tspec_is_scalar(tn->tn_type->t_tspec)) {
-		/* controlling expressions must have scalar type */
-		error(204);
-		tn = NULL;
-	}
+		tn = check_controlling_expression(tn);
 
 	pushctrl(T_WHILE);
 	cstk->c_loop = 1;
@@ -763,14 +777,7 @@ do2(tnode_t *tn)
 		reached = 1;
 
 	if (tn != NULL)
-		tn = cconv(tn);
-	if (tn != NULL)
-		tn = promote(NOOP, 0, tn);
-	if (tn != NULL && !tspec_is_scalar(tn->tn_type->t_tspec)) {
-		/* controlling expressions must have scalar type */
-		error(204);
-		tn = NULL;
-	}
+		tn = check_controlling_expression(tn);
 
 	if (tn != NULL && tn->tn_op == CON) {
 		if (tspec_is_int(tn->tn_type->t_tspec)) {
@@ -828,14 +835,7 @@ for1(tnode_t *tn1, tnode_t *tn2, tnode_t
 		expr(tn1, 0, 0, 1);
 
 	if (tn2 != NULL)
-		tn2 = cconv(tn2);
-	if (tn2 != NULL)
-		tn2 = promote(NOOP, 0, tn2);
-	if (tn2 != NULL && !tspec_is_scalar(tn2->tn_type->t_tspec)) {
-		/* controlling expressions must have scalar type */
-		error(204);
-		tn2 = NULL;
-	}
+		tn2 = check_controlling_expression(tn2);
 	if (tn2 != NULL)
 		expr(tn2, 0, 1, 1);
 

Added files:

Index: src/tests/usr.bin/xlint/lint1/d_fold_test.c
diff -u /dev/null src/tests/usr.bin/xlint/lint1/d_fold_test.c:1.1
--- /dev/null	Thu Dec 31 18:51:28 2020
+++ src/tests/usr.bin/xlint/lint1/d_fold_test.c	Thu Dec 31 18:51:28 2020
@@ -0,0 +1,70 @@
+# 2 "d_fold_test.c"
+
+/*
+ * Test how expressions are handled in a context where they are tested for
+ * truthiness, such as in the condition of an if statement.
+ */
+
+struct s {
+	int member;
+};
+
+union u {
+	int member;
+};
+
+enum e {
+	E
+};
+
+struct arr {
+	int arr[4];
+};
+
+/* C99 6.2.5p2 */
+void if_Bool(_Bool b)			{ if (b) return; }
+
+/* C99 6.2.5p3 */
+void if_char(char c)			{ if (c) return; }
+
+/* C99 6.2.5p4 */
+void if_signed_char(signed char sc)	{ if (sc) return; }
+void if_short_int(short s)		{ if (s) return; }
+void if_int(int i)			{ if (i) return; }
+void if_long_int(long int l)		{ if (l) return; }
+void if_long_long_int(long long int ll)	{ if (ll) return; }
+
+/* C99 6.2.5p6 */
+void if_unsigned_char(unsigned char uc)			{ if (uc) return; }
+void if_unsigned_short_int(unsigned short us)		{ if (us) return; }
+void if_unsigned_int(unsigned int ui)			{ if (ui) return; }
+void if_unsigned_long_int(unsigned long int ul)		{ if (ul) return; }
+void if_unsigned_long_long_int(unsigned long long int ull) { if (ull) return; }
+
+/* C99 6.2.5p10 */
+void if_float(float f)			{ if (f) return; }
+void if_double(double d)		{ if (d) return; }
+void if_long_double(long double ld)	{ if (ld) return; }
+
+/* C99 6.2.5p11 */
+void if_float_Complex(float _Complex fc)		{ if (fc) return; }
+void if_double_Complex(double _Complex dc)		{ if (dc) return; }
+void if_long_double_Complex(long double _Complex ldc)	{ if (ldc) return; }
+
+/* C99 6.2.5p16 */
+void if_enum(enum e e)			{ if (e) return; }
+
+/* C99 6.2.5p20 */
+void if_array(struct arr arr)		{ if (arr.arr) return; }
+void if_struct(struct s s)		{ if (s) return; }
+void if_union(union u u)		{ if (u) return; }
+void if_function(void (*f)(void))	{ if (f) return; }
+void if_pointer(void *p)		{ if (p) return; }
+
+/* C99 6.8.5 */
+void while_struct(struct s s)		{ while (s) return; }
+void for_struct(struct s s)		{ for (;s;) return; }
+void do_while_struct(struct s s)	{ do { return; } while (s); }
+
+/* C99 6.5.15 does not require a scalar type, curiously. */
+int conditional_struct(struct s s)	{ return s ? 1 : 2; }
Index: src/tests/usr.bin/xlint/lint1/d_fold_test.exp
diff -u /dev/null src/tests/usr.bin/xlint/lint1/d_fold_test.exp:1.1
--- /dev/null	Thu Dec 31 18:51:28 2020
+++ src/tests/usr.bin/xlint/lint1/d_fold_test.exp	Thu Dec 31 18:51:28 2020
@@ -0,0 +1,16 @@
+d_fold_test.c(58): controlling expressions must have scalar type [204]
+d_fold_test.c(58): warning: argument arr unused in function if_array [231]
+d_fold_test.c(59): controlling expressions must have scalar type [204]
+d_fold_test.c(59): warning: argument s unused in function if_struct [231]
+d_fold_test.c(60): controlling expressions must have scalar type [204]
+d_fold_test.c(60): warning: argument u unused in function if_union [231]
+d_fold_test.c(65): controlling expressions must have scalar type [204]
+d_fold_test.c(65): warning: argument s unused in function while_struct [231]
+d_fold_test.c(66): controlling expressions must have scalar type [204]
+d_fold_test.c(66): warning: end-of-loop code not reached [223]
+d_fold_test.c(66): warning: argument s unused in function for_struct [231]
+d_fold_test.c(67): controlling expressions must have scalar type [204]
+d_fold_test.c(67): warning: argument s unused in function do_while_struct [231]
+d_fold_test.c(70): first operand must have scalar type, op ? : [170]
+d_fold_test.c(70): warning: function conditional_struct expects to return value [214]
+d_fold_test.c(70): warning: argument s unused in function conditional_struct [231]

Reply via email to