Module Name:    src
Committed By:   rillig
Date:           Sun Jun 27 20:47:14 UTC 2021

Modified Files:
        src/tests/usr.bin/xlint/lint1: c11_generic_expression.c
            c11_generic_expression.exp msg_345.c
        src/usr.bin/xlint/lint1: cgram.y externs1.h lint1.h tree.c

Log Message:
lint: fix result type of _Generic expressions


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 \
    src/tests/usr.bin/xlint/lint1/c11_generic_expression.c \
    src/tests/usr.bin/xlint/lint1/c11_generic_expression.exp
cvs rdiff -u -r1.1 -r1.2 src/tests/usr.bin/xlint/lint1/msg_345.c
cvs rdiff -u -r1.236 -r1.237 src/usr.bin/xlint/lint1/cgram.y
cvs rdiff -u -r1.111 -r1.112 src/usr.bin/xlint/lint1/externs1.h
cvs rdiff -u -r1.106 -r1.107 src/usr.bin/xlint/lint1/lint1.h
cvs rdiff -u -r1.290 -r1.291 src/usr.bin/xlint/lint1/tree.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/c11_generic_expression.c
diff -u src/tests/usr.bin/xlint/lint1/c11_generic_expression.c:1.2 src/tests/usr.bin/xlint/lint1/c11_generic_expression.c:1.3
--- src/tests/usr.bin/xlint/lint1/c11_generic_expression.c:1.2	Sun Jun 27 19:59:23 2021
+++ src/tests/usr.bin/xlint/lint1/c11_generic_expression.c	Sun Jun 27 20:47:13 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: c11_generic_expression.c,v 1.2 2021/06/27 19:59:23 rillig Exp $	*/
+/*	$NetBSD: c11_generic_expression.c,v 1.3 2021/06/27 20:47:13 rillig Exp $	*/
 # 3 "c11_generic_expression.c"
 
 /*
@@ -20,13 +20,14 @@
 const char *
 classify_type_without_default(double var)
 {
+	/* expect-2: argument 'var' unused */
+
 	return _Generic(var,
 	    long double: "long double",
 	    long long: "long long",
 	    unsigned: "unsigned"
 	);
-	/* expect-7: argument 'var' unused */
-	/* expect-2: type mismatch (pointer to const char) and (double) *//* FIXME */
+	/* expect-1: expects to return value [214] */
 }
 
 /*
@@ -35,14 +36,14 @@ classify_type_without_default(double var
 const char *
 classify_type_with_default(double var)
 {
+	/* expect-2: argument 'var' unused */
+
 	return _Generic(var,
 	    long double: "long double",
 	    long long: "long long",
 	    unsigned: "unsigned",
 	    default: "unknown"
 	);
-	/* expect-8: argument 'var' unused */
-	/* expect-2: type mismatch (pointer to const char) and (double) *//* FIXME */
 }
 
 /*
@@ -51,9 +52,10 @@ classify_type_with_default(double var)
 const char *
 classify_char(char c)
 {
+	/* expect-2: argument 'c' unused */
+
 	return _Generic(c,
 	    char: "yes",
 	    default: 0.0
 	);
-	/* expect-1: (pointer to const char) and integer (char) [183] */
 }
Index: src/tests/usr.bin/xlint/lint1/c11_generic_expression.exp
diff -u src/tests/usr.bin/xlint/lint1/c11_generic_expression.exp:1.2 src/tests/usr.bin/xlint/lint1/c11_generic_expression.exp:1.3
--- src/tests/usr.bin/xlint/lint1/c11_generic_expression.exp:1.2	Sun Jun 27 19:59:23 2021
+++ src/tests/usr.bin/xlint/lint1/c11_generic_expression.exp	Sun Jun 27 20:47:13 2021
@@ -1,5 +1,4 @@
-c11_generic_expression.c(27): error: return value type mismatch (pointer to const char) and (double) [211]
+c11_generic_expression.c(29): warning: function classify_type_without_default expects to return value [214]
 c11_generic_expression.c(21): warning: argument 'var' unused in function 'classify_type_without_default' [231]
-c11_generic_expression.c(43): error: return value type mismatch (pointer to const char) and (double) [211]
-c11_generic_expression.c(36): warning: argument 'var' unused in function 'classify_type_with_default' [231]
-c11_generic_expression.c(57): warning: illegal combination of pointer (pointer to const char) and integer (char) [183]
+c11_generic_expression.c(37): warning: argument 'var' unused in function 'classify_type_with_default' [231]
+c11_generic_expression.c(53): warning: argument 'c' unused in function 'classify_char' [231]

Index: src/tests/usr.bin/xlint/lint1/msg_345.c
diff -u src/tests/usr.bin/xlint/lint1/msg_345.c:1.1 src/tests/usr.bin/xlint/lint1/msg_345.c:1.2
--- src/tests/usr.bin/xlint/lint1/msg_345.c:1.1	Sun Jun 27 19:10:29 2021
+++ src/tests/usr.bin/xlint/lint1/msg_345.c	Sun Jun 27 20:47:13 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: msg_345.c,v 1.1 2021/06/27 19:10:29 rillig Exp $	*/
+/*	$NetBSD: msg_345.c,v 1.2 2021/06/27 20:47:13 rillig Exp $	*/
 # 3 "msg_345.c"
 
 // Test for message: generic selection requires C11 or later [345]
@@ -10,5 +10,5 @@ int
 test(int x)
 {
 	/* expect+1: generic selection requires C11 or later [345] */
-	return _Generic(x, default: 3);
+	return _Generic(x, default: 3) + x;
 }

Index: src/usr.bin/xlint/lint1/cgram.y
diff -u src/usr.bin/xlint/lint1/cgram.y:1.236 src/usr.bin/xlint/lint1/cgram.y:1.237
--- src/usr.bin/xlint/lint1/cgram.y:1.236	Sun Jun 27 19:10:29 2021
+++ src/usr.bin/xlint/lint1/cgram.y	Sun Jun 27 20:47:13 2021
@@ -1,5 +1,5 @@
 %{
-/* $NetBSD: cgram.y,v 1.236 2021/06/27 19:10:29 rillig Exp $ */
+/* $NetBSD: cgram.y,v 1.237 2021/06/27 20:47:13 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -35,7 +35,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: cgram.y,v 1.236 2021/06/27 19:10:29 rillig Exp $");
+__RCSID("$NetBSD: cgram.y,v 1.237 2021/06/27 20:47:13 rillig Exp $");
 #endif
 
 #include <limits.h>
@@ -139,6 +139,7 @@ anonymize(sym_t *s)
 	strg_t	*y_string;
 	pqinf_t	*y_pqinf;
 	bool	y_seen_statement;
+	struct generic_association_types *y_types;
 };
 
 %token			T_LBRACE T_RBRACE T_LBRACK T_RBRACK T_LPAREN T_RPAREN
@@ -338,6 +339,8 @@ anonymize(sym_t *s)
 %type	<y_range>	range
 %type	<y_seen_statement> block_item_list
 %type	<y_seen_statement> block_item
+%type	<y_types>	generic_assoc_list
+%type	<y_types>	generic_association
 
 
 %%
@@ -1685,18 +1688,29 @@ generic_selection:		/* C11 6.5.1.1 */
 	  T_GENERIC T_LPAREN expr T_COMMA generic_assoc_list T_RPAREN {
 	  	/* generic selection requires C11 or later */
 	  	c11ism(345);
-		$$ = $3;
+		$$ = build_generic_selection($3, $5);
 	  }
 	;
 
 generic_assoc_list:		/* C11 6.5.1.1 */
 	  generic_association
-	| generic_assoc_list T_COMMA generic_association
+	| generic_assoc_list T_COMMA generic_association {
+		$3->gat_prev = $1;
+		$$ = $3;
+	  }
 	;
 
 generic_association:		/* C11 6.5.1.1 */
-	  type_name T_COLON expr
-	| T_DEFAULT T_COLON expr
+	  type_name T_COLON expr {
+		$$ = getblk(sizeof(*$$));
+		$$->gat_arg = $1;
+		$$->gat_result = $3;
+	  }
+	| T_DEFAULT T_COLON expr {
+		$$ = getblk(sizeof(*$$));
+		$$->gat_arg = NULL;
+		$$->gat_result = $3;
+	  }
 	;
 
 do_statement:			/* C99 6.8.5 */

Index: src/usr.bin/xlint/lint1/externs1.h
diff -u src/usr.bin/xlint/lint1/externs1.h:1.111 src/usr.bin/xlint/lint1/externs1.h:1.112
--- src/usr.bin/xlint/lint1/externs1.h:1.111	Sun Jun 20 20:59:08 2021
+++ src/usr.bin/xlint/lint1/externs1.h	Sun Jun 27 20:47:13 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: externs1.h,v 1.111 2021/06/20 20:59:08 rillig Exp $	*/
+/*	$NetBSD: externs1.h,v 1.112 2021/06/27 20:47:13 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -208,6 +208,9 @@ extern	tnode_t	*expr_new_constant(type_t
 extern	tnode_t	*new_name_node(sym_t *, int);
 extern	tnode_t	*new_string_node(strg_t *);
 extern	sym_t	*struct_or_union_member(tnode_t *, op_t, sym_t *);
+extern	tnode_t	*build_generic_selection(const tnode_t *,
+		    struct generic_association_types *);
+
 extern	tnode_t	*build(op_t, tnode_t *, tnode_t *);
 extern	tnode_t	*cconv(tnode_t *);
 extern	bool	is_typeok_bool_operand(const tnode_t *);

Index: src/usr.bin/xlint/lint1/lint1.h
diff -u src/usr.bin/xlint/lint1/lint1.h:1.106 src/usr.bin/xlint/lint1/lint1.h:1.107
--- src/usr.bin/xlint/lint1/lint1.h:1.106	Sun Jun 27 08:20:50 2021
+++ src/usr.bin/xlint/lint1/lint1.h	Sun Jun 27 20:47:13 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: lint1.h,v 1.106 2021/06/27 08:20:50 rillig Exp $ */
+/* $NetBSD: lint1.h,v 1.107 2021/06/27 20:47:13 rillig Exp $ */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All Rights Reserved.
@@ -316,6 +316,12 @@ typedef	struct tnode {
 #define	tn_val		tn_u._tn_val
 #define	tn_string	tn_u._tn_string
 
+struct generic_association_types {
+	type_t *gat_arg;	/* NULL means default or error */
+	tnode_t *gat_result;	/* NULL means error */
+	struct generic_association_types *gat_prev;
+};
+
 /*
  * For nested declarations a stack exists, which holds all information
  * needed for the current level. dcs points to the innermost element of this

Index: src/usr.bin/xlint/lint1/tree.c
diff -u src/usr.bin/xlint/lint1/tree.c:1.290 src/usr.bin/xlint/lint1/tree.c:1.291
--- src/usr.bin/xlint/lint1/tree.c:1.290	Sun Jun 20 20:48:25 2021
+++ src/usr.bin/xlint/lint1/tree.c	Sun Jun 27 20:47:13 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: tree.c,v 1.290 2021/06/20 20:48:25 rillig Exp $	*/
+/*	$NetBSD: tree.c,v 1.291 2021/06/27 20:47:13 rillig Exp $	*/
 
 /*
  * Copyright (c) 1994, 1995 Jochen Pohl
@@ -37,7 +37,7 @@
 
 #include <sys/cdefs.h>
 #if defined(__RCSID) && !defined(lint)
-__RCSID("$NetBSD: tree.c,v 1.290 2021/06/20 20:48:25 rillig Exp $");
+__RCSID("$NetBSD: tree.c,v 1.291 2021/06/27 20:47:13 rillig Exp $");
 #endif
 
 #include <float.h>
@@ -468,6 +468,20 @@ struct_or_union_member(tnode_t *tn, op_t
 	return msym;
 }
 
+tnode_t *
+build_generic_selection(const tnode_t *expr,
+			struct generic_association_types *sel)
+{
+	tnode_t *default_result = NULL;
+
+	for (; sel != NULL; sel = sel->gat_prev)
+		if (expr != NULL && sel->gat_arg == expr->tn_type)
+			return sel->gat_result;
+		else if (sel->gat_arg == NULL)
+			default_result = sel->gat_result;
+	return default_result;
+}
+
 /*
  * Create a tree node. Called for most operands except function calls,
  * sizeof and casts.

Reply via email to