diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-06-03 22:58:33 +0200 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-06-09 01:32:15 +0200 |
commit | 966dd78f873a2ee9a394d3b2267d121a6dfcd1e9 (patch) | |
tree | ebf2e8b3498a86a4d9e89410bfd464f6f67df2a1 | |
parent | 08256ea9dfd159b3d7ab0eba2eba36afb8025195 (diff) | |
download | sparse-966dd78f873a2ee9a394d3b2267d121a6dfcd1e9.tar.gz |
generic: fix crash when nothing match
The code for the generic selection doesn't take in account
the fact that the default entry could be absent.
Catch the case where nothing matches and issue an error.
Fixes: c100a7ab2504f9e6fe6b6d3f9a010a8ea5ed30a3
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | evaluate.c | 8 | ||||
-rw-r--r-- | validation/generic-bad0.c | 23 |
2 files changed, 29 insertions, 2 deletions
@@ -3299,11 +3299,15 @@ static struct symbol *evaluate_generic_selection(struct expression *expr) continue; res = map->expr; - goto end; + goto found; } res = expr->def; + if (!res) { + sparse_error(expr->pos, "no generic selection for '%s'", show_typename(ctrl)); + return NULL; + } -end: +found: *expr = *res; return evaluate_expression(expr); } diff --git a/validation/generic-bad0.c b/validation/generic-bad0.c new file mode 100644 index 00000000..acc3d5e7 --- /dev/null +++ b/validation/generic-bad0.c @@ -0,0 +1,23 @@ +struct s; + +void foo(int n) +{ + _Generic(n, default: 1, default: 2); + _Generic(n, int[n]:0, default:1); + _Generic(n, struct s:0, default:1); + _Generic(n, void:0, default:1); + _Generic(n, void (void):0, default:1); + _Generic(&n, int:5, signed int:7, default:23); + _Generic(n, void *:5); +} + +/* + * check-name: generic-bad0 + * + * check-error-start +generic-bad0.c:5:33: warning: multiple default in generic expression +generic-bad0.c:5:30: note: previous was here +generic-bad0.c:6:25: warning: Variable length array is used. +generic-bad0.c:11:17: error: no generic selection for 'int [addressable] n' + * check-error-end + */ |