Casts should drop qualifiers but Sparse doesn't do this yet. The fix seems pretty simple: after having evaluated the type of the cast, if this type is a SYM_NODE and contains qualifiers, make a copy of the type with the qualifiers removed and use this copy as the type. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- This seems a bit too simple to be true but it seems correct and it passes the testcase here under and a related testcase from GCC. evaluate.c | 13 +++++++++++++ validation/eval/cast-unqual.c | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 validation/eval/cast-unqual.c diff --git a/evaluate.c b/evaluate.c index 43a611696787..004cd2f9b339 100644 --- a/evaluate.c +++ b/evaluate.c @@ -2998,6 +2998,18 @@ static struct symbol *evaluate_compound_literal(struct expression *expr, struct return sym; } +static struct symbol *unqualify_type(struct symbol *ctype) +{ + if (ctype->type == SYM_NODE && (ctype->ctype.modifiers & MOD_QUALIFIER)) { + struct symbol *unqual = alloc_symbol(ctype->pos, 0); + + *unqual = *ctype; + unqual->ctype.modifiers &= ~MOD_QUALIFIER; + return unqual; + } + return ctype; +} + static struct symbol *evaluate_cast(struct expression *expr) { struct expression *source = expr->cast_expression; @@ -3025,6 +3037,7 @@ static struct symbol *evaluate_cast(struct expression *expr) return evaluate_compound_literal(expr, source); ctype = examine_symbol_type(expr->cast_type); + ctype = unqualify_type(ctype); expr->ctype = ctype; expr->cast_type = ctype; diff --git a/validation/eval/cast-unqual.c b/validation/eval/cast-unqual.c new file mode 100644 index 000000000000..0ea318875c96 --- /dev/null +++ b/validation/eval/cast-unqual.c @@ -0,0 +1,14 @@ +#define cvr const volatile restrict + +_Static_assert([typeof((cvr int) 0)] == [int]); +_Static_assert([typeof((cvr int *) 0)] == [cvr int *]); + +static int *function(volatile int x) +{ + extern typeof((typeof(x)) (x)) y; + return &y; +} + +/* + * check-name: cast-unqual + */ -- 2.29.2