aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-06-20 23:40:33 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2020-06-20 23:40:33 +0200
commit8451604a75f8bbaaa65a57819134f2dea5a4c29d (patch)
treee99ca729c182d2e2650b96f69855643f4e2d99a8
parentfdbb6dbe1d394dfae5a0d9c6d1c550c07678bf16 (diff)
parentad9670d0530c31d171103ac3ea60c8aba20f9a80 (diff)
downloadsparse-8451604a75f8bbaaa65a57819134f2dea5a4c29d.tar.gz
Merge branch 'fix-gensel'
-rw-r--r--evaluate.c33
-rw-r--r--validation/generic-bad0.c4
-rw-r--r--validation/generic-dr481.c16
3 files changed, 50 insertions, 3 deletions
diff --git a/evaluate.c b/evaluate.c
index 95aef4dc..aa0f2080 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -3287,15 +3287,42 @@ static struct symbol *evaluate_generic_selection(struct expression *expr)
{
struct type_expression *map;
struct expression *res;
+ struct symbol source;
struct symbol *ctrl;
- if (!(ctrl = evaluate_expression(expr->control)))
+ if (!evaluate_expression(expr->control))
+ return NULL;
+ if (!(ctrl = degenerate(expr->control)))
return NULL;
+ source = *ctrl;
+ source.ctype.modifiers &= ~(MOD_QUALIFIER|MOD_ATOMIC);
for (map = expr->map; map; map = map->next) {
- if (!evaluate_symbol(map->type))
+ struct symbol *stype = map->type;
+ struct symbol *base;
+
+ if (!evaluate_symbol(stype))
+ continue;
+
+ if (stype->type == SYM_NODE)
+ base = stype->ctype.base_type;
+
+ if (base->type == SYM_ARRAY && base->array_size) {
+ get_expression_value_silent(base->array_size);
+ if (base->array_size->type == EXPR_VALUE)
+ continue;
+ sparse_error(stype->pos, "variable length array type in generic selection");
continue;
- if (!type_selection(ctrl, map->type))
+ }
+ if (is_func_type(stype)) {
+ sparse_error(stype->pos, "function type in generic selection");
+ continue;
+ }
+ if (stype->bit_size <= 0 || is_void_type(stype)) {
+ sparse_error(stype->pos, "incomplete type in generic selection");
+ continue;
+ }
+ if (!type_selection(&source, stype))
continue;
res = map->expr;
diff --git a/validation/generic-bad0.c b/validation/generic-bad0.c
index acc3d5e7..d11030db 100644
--- a/validation/generic-bad0.c
+++ b/validation/generic-bad0.c
@@ -18,6 +18,10 @@ void foo(int n)
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:6:21: error: variable length array type in generic selection
+generic-bad0.c:7:21: error: incomplete type in generic selection
+generic-bad0.c:8:21: error: incomplete type in generic selection
+generic-bad0.c:9:21: error: function type in generic selection
generic-bad0.c:11:17: error: no generic selection for 'int [addressable] n'
* check-error-end
*/
diff --git a/validation/generic-dr481.c b/validation/generic-dr481.c
new file mode 100644
index 00000000..a2d27b98
--- /dev/null
+++ b/validation/generic-dr481.c
@@ -0,0 +1,16 @@
+static char const* a = _Generic("bla", char*: "blu");
+static char const* b = _Generic("bla", char[4]: "blu");
+static char const* c = _Generic((int const){ 0 }, int: "blu");
+static char const* d = _Generic((int const){ 0 }, int const: "blu");
+static char const* e = _Generic(+(int const){ 0 }, int: "blu");
+static char const* f = _Generic(+(int const){ 0 }, int const: "blu");
+
+/*
+ * check-name: generic-dr481
+ *
+ * check-error-start
+generic-dr481.c:2:32: error: no generic selection for 'char *'
+generic-dr481.c:4:32: error: no generic selection for 'int const [toplevel]'
+generic-dr481.c:6:32: error: no generic selection for 'int'
+ * check-error-end
+ */