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.