aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-18 22:34:41 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-11-19 21:05:56 +0100
commit009181de300b2f0e6f9e64d4694e07aa12808c57 (patch)
tree869ba7208ffb2f1b8d965ba761c3f44e8a291f0c
parent2c5eeff0f1741761196b8b2cfc86b71ef9ef9548 (diff)
downloadsparse-009181de300b2f0e6f9e64d4694e07aa12808c57.tar.gz
fix assignment check with function attribute
It's OK to assign a non-qualified type to the corresponding const- or -volatile-qualified type (same for 'restrict'). For modifiers like __pure or __noreturn, it's the opposite: it's OK to assign the qualified version to the corresponding non-qualified type. Allow this by using type_difference() with the appropriate mask when checking assignments. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--evaluate.c8
-rw-r--r--symbol.h2
2 files changed, 8 insertions, 2 deletions
diff --git a/evaluate.c b/evaluate.c
index b9d3cfe3..863750fa 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -658,7 +658,7 @@ static struct symbol *evaluate_ptr_add(struct expression *expr, struct symbol *i
static void examine_fn_arguments(struct symbol *fn);
-#define MOD_IGN (MOD_QUALIFIER | MOD_PURE)
+#define MOD_IGN (MOD_QUALIFIER | MOD_FUN_ATTR)
const char *type_difference(struct ctype *c1, struct ctype *c2,
unsigned long mod1, unsigned long mod2)
@@ -1429,6 +1429,7 @@ static int check_assignment_types(struct symbol *target, struct expression **rp,
if (tclass == TYPE_PTR) {
unsigned long mod1, mod2;
+ unsigned long modl, modr;
struct symbol *b1, *b2;
// NULL pointer is always OK
int is_null = is_null_pointer_constant(*rp);
@@ -1471,7 +1472,10 @@ static int check_assignment_types(struct symbol *target, struct expression **rp,
goto Cast;
}
/* It's OK if the target is more volatile or const than the source */
- *typediff = type_difference(&t->ctype, &s->ctype, 0, mod1);
+ /* It's OK if the source is more pure/noreturn than the target */
+ modr = mod1 & ~MOD_REV_QUAL;
+ modl = mod2 & MOD_REV_QUAL;
+ *typediff = type_difference(&t->ctype, &s->ctype, modl, modr);
if (*typediff)
return 0;
return 1;
diff --git a/symbol.h b/symbol.h
index 516b6136..2465d6d8 100644
--- a/symbol.h
+++ b/symbol.h
@@ -253,6 +253,8 @@ struct symbol {
#define MOD_TYPEOF (MOD_QUALIFIER | MOD_NOCAST | MOD_SPECIFIER)
/* modifiers for funtion attributes */
#define MOD_FUN_ATTR (MOD_PURE|MOD_NORETURN)
+/* like cvr-qualifiers but 'reversed' (OK: source <= target) */
+#define MOD_REV_QUAL (MOD_PURE|MOD_NORETURN)
/* Current parsing/evaluation function */