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.