From e06c9268c4e96f4d011d46ee8bbe5de7e264d0fa Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 19 Jun 2020 15:42:07 +0200 Subject: gensel: add testcases from DR481 Following the resolution of DR481, the controlling expression is subject to a few different rules. Add the testcases from this defect report. Signed-off-by: Luc Van Oostenryck --- validation/generic-dr481.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 validation/generic-dr481.c diff --git a/validation/generic-dr481.c b/validation/generic-dr481.c new file mode 100644 index 00000000..2ed15c9b --- /dev/null +++ b/validation/generic-dr481.c @@ -0,0 +1,17 @@ +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-known-to-fail + * + * 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 + */ -- cgit 1.2.3-korg From 383e7d4f1b745057d73abc3bbf3d6f2b6f47ffc2 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 19 Jun 2020 14:55:07 +0200 Subject: gensel: use temporary variable in generic selection Use a temporary variable for 'map->type' to make the expressions in the following patches more readable. Signed-off-by: Luc Van Oostenryck --- evaluate.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/evaluate.c b/evaluate.c index 95aef4dc..cf40eed4 100644 --- a/evaluate.c +++ b/evaluate.c @@ -3293,9 +3293,11 @@ static struct symbol *evaluate_generic_selection(struct expression *expr) return NULL; for (map = expr->map; map; map = map->next) { - if (!evaluate_symbol(map->type)) + struct symbol *stype = map->type; + + if (!evaluate_symbol(stype)) continue; - if (!type_selection(ctrl, map->type)) + if (!type_selection(ctrl, stype)) continue; res = map->expr; -- cgit 1.2.3-korg From 2878dae725a94a7f6a3f52677b2ec78c93e93765 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 19 Jun 2020 15:01:10 +0200 Subject: gensel: controlling expression must be lvalue converted Following the resolution of DR481, the controlling expression of a generic selection must be lvalue converted. In other words, the qualifiers must be ignored. Reported-by: Marco Elver Signed-off-by: Luc Van Oostenryck --- evaluate.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/evaluate.c b/evaluate.c index cf40eed4..d8615a89 100644 --- a/evaluate.c +++ b/evaluate.c @@ -3287,17 +3287,20 @@ 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))) return NULL; + source = *ctrl; + source.ctype.modifiers &= ~(MOD_QUALIFIER|MOD_ATOMIC); for (map = expr->map; map; map = map->next) { struct symbol *stype = map->type; if (!evaluate_symbol(stype)) continue; - if (!type_selection(ctrl, stype)) + if (!type_selection(&source, stype)) continue; res = map->expr; -- cgit 1.2.3-korg From 1d91e40cb10a82c69091f3bf2b91ffd9837d7725 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 19 Jun 2020 15:01:10 +0200 Subject: gensel: controlling expression must be pointer-converted Following the resolution of DR481, the controlling expression of a generic selection must be array-to-pointer converted and function-to-pointer converted. Do this by adding a call to degenerate(). Reported-by: Marco Elver Signed-off-by: Luc Van Oostenryck --- evaluate.c | 4 +++- validation/generic-dr481.c | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/evaluate.c b/evaluate.c index d8615a89..491dfa3c 100644 --- a/evaluate.c +++ b/evaluate.c @@ -3290,7 +3290,9 @@ static struct symbol *evaluate_generic_selection(struct expression *expr) 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; diff --git a/validation/generic-dr481.c b/validation/generic-dr481.c index 2ed15c9b..a2d27b98 100644 --- a/validation/generic-dr481.c +++ b/validation/generic-dr481.c @@ -7,7 +7,6 @@ static char const* f = _Generic(+(int const){ 0 }, int const: "blu"); /* * check-name: generic-dr481 - * check-known-to-fail * * check-error-start generic-dr481.c:2:32: error: no generic selection for 'char *' -- cgit 1.2.3-korg From ad9670d0530c31d171103ac3ea60c8aba20f9a80 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Fri, 19 Jun 2020 15:02:19 +0200 Subject: gensel: validate the type of the associations The type in a generic association must correspond to a complete type and not a variably modified type. Add validation for this. Signed-off-by: Luc Van Oostenryck --- evaluate.c | 20 ++++++++++++++++++++ validation/generic-bad0.c | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/evaluate.c b/evaluate.c index 491dfa3c..aa0f2080 100644 --- a/evaluate.c +++ b/evaluate.c @@ -3299,9 +3299,29 @@ static struct symbol *evaluate_generic_selection(struct expression *expr) source.ctype.modifiers &= ~(MOD_QUALIFIER|MOD_ATOMIC); for (map = expr->map; map; map = map->next) { 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 (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; 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 */ -- cgit 1.2.3-korg