Module Name:    src
Committed By:   rillig
Date:           Fri Jan  8 02:11:45 UTC 2021

Modified Files:
        src/tests/usr.bin/xlint/lint1: d_fold_test.c d_fold_test.exp msg_204.c
            msg_204.exp
        src/usr.bin/xlint/lint1: func.c

Log Message:
lint: fix function as controlling expression (since 2020-12-31)

It's perfectly valid to directly use a function name as the controlling
expression of an if statement.  That function name is converted
implicitly to a pointer to that function, and that is a scalar value
then.

Spotted by christos in lib/libpthread/pthread.c:634.


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/d_fold_test.c \
    src/tests/usr.bin/xlint/lint1/d_fold_test.exp
cvs rdiff -u -r1.2 -r1.3 src/tests/usr.bin/xlint/lint1/msg_204.c \
    src/tests/usr.bin/xlint/lint1/msg_204.exp
cvs rdiff -u -r1.52 -r1.53 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/tests/usr.bin/xlint/lint1/d_fold_test.c
diff -u src/tests/usr.bin/xlint/lint1/d_fold_test.c:1.1 src/tests/usr.bin/xlint/lint1/d_fold_test.c:1.2
--- src/tests/usr.bin/xlint/lint1/d_fold_test.c:1.1	Thu Dec 31 18:51:28 2020
+++ src/tests/usr.bin/xlint/lint1/d_fold_test.c	Fri Jan  8 02:11:45 2021
@@ -58,7 +58,7 @@ void if_enum(enum e e)			{ if (e) return
 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_function(void)			{ if (if_function) return; }
 void if_pointer(void *p)		{ if (p) return; }
 
 /* C99 6.8.5 */
Index: src/tests/usr.bin/xlint/lint1/d_fold_test.exp
diff -u src/tests/usr.bin/xlint/lint1/d_fold_test.exp:1.1 src/tests/usr.bin/xlint/lint1/d_fold_test.exp:1.2
--- src/tests/usr.bin/xlint/lint1/d_fold_test.exp:1.1	Thu Dec 31 18:51:28 2020
+++ src/tests/usr.bin/xlint/lint1/d_fold_test.exp	Fri Jan  8 02:11:45 2021
@@ -1,5 +1,3 @@
-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]

Index: src/tests/usr.bin/xlint/lint1/msg_204.c
diff -u src/tests/usr.bin/xlint/lint1/msg_204.c:1.2 src/tests/usr.bin/xlint/lint1/msg_204.c:1.3
--- src/tests/usr.bin/xlint/lint1/msg_204.c:1.2	Fri Jan  8 01:40:03 2021
+++ src/tests/usr.bin/xlint/lint1/msg_204.c	Fri Jan  8 02:11:45 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_204.c,v 1.2 2021/01/08 01:40:03 rillig Exp $	*/
+/*	$NetBSD: msg_204.c,v 1.3 2021/01/08 02:11:45 rillig Exp $	*/
 # 3 "msg_204.c"
 
 // Test for message: controlling expressions must have scalar type [204]
@@ -32,3 +32,70 @@ bug_between_2020_12_31_and_2021_01_08(vo
 	if (function_pointer)
 		function_pointer();
 }
+
+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)			{ if (if_function) 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 for the '?:' operator does not explicitly mention that the
+ * controlling expression must have a scalar type, curiously.
+ */
+int conditional_struct(struct s s)	{ return s ? 1 : 2; }
Index: src/tests/usr.bin/xlint/lint1/msg_204.exp
diff -u src/tests/usr.bin/xlint/lint1/msg_204.exp:1.2 src/tests/usr.bin/xlint/lint1/msg_204.exp:1.3
--- src/tests/usr.bin/xlint/lint1/msg_204.exp:1.2	Fri Jan  8 01:40:03 2021
+++ src/tests/usr.bin/xlint/lint1/msg_204.exp	Fri Jan  8 02:11:45 2021
@@ -1,2 +1,14 @@
-msg_204.c(19): controlling expressions must have scalar type [204]
-msg_204.c(28): controlling expressions must have scalar type [204]
+msg_204.c(87): controlling expressions must have scalar type [204]
+msg_204.c(87): warning: argument s unused in function if_struct [231]
+msg_204.c(88): controlling expressions must have scalar type [204]
+msg_204.c(88): warning: argument u unused in function if_union [231]
+msg_204.c(93): controlling expressions must have scalar type [204]
+msg_204.c(93): warning: argument s unused in function while_struct [231]
+msg_204.c(94): controlling expressions must have scalar type [204]
+msg_204.c(94): warning: end-of-loop code not reached [223]
+msg_204.c(94): warning: argument s unused in function for_struct [231]
+msg_204.c(95): controlling expressions must have scalar type [204]
+msg_204.c(95): warning: argument s unused in function do_while_struct [231]
+msg_204.c(101): first operand must have scalar type, op ? : [170]
+msg_204.c(101): warning: function conditional_struct expects to return value [214]
+msg_204.c(101): warning: argument s unused in function conditional_struct [231]

Index: src/usr.bin/xlint/lint1/func.c
diff -u src/usr.bin/xlint/lint1/func.c:1.52 src/usr.bin/xlint/lint1/func.c:1.53
--- src/usr.bin/xlint/lint1/func.c:1.52	Fri Jan  8 01:40:03 2021
+++ src/usr.bin/xlint/lint1/func.c	Fri Jan  8 02:11:45 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: func.c,v 1.52 2021/01/08 01:40:03 rillig Exp $	*/
+/*	$NetBSD: func.c,v 1.53 2021/01/08 02:11:45 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.52 2021/01/08 01:40:03 rillig Exp $");
+__RCSID("$NetBSD: func.c,v 1.53 2021/01/08 02:11:45 rillig Exp $");
 #endif
 
 #include <stdlib.h>
@@ -537,16 +537,13 @@ default_label(void)
 static tnode_t *
 check_controlling_expression(tnode_t *tn)
 {
-	// FIXME: dereference before null check
-	// FIXME: This is evaluated too early; see test msg_204
-	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)) {
+	if (tn != NULL && !tspec_is_scalar(tn->tn_type->t_tspec)) {
 		/* 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 */

Reply via email to