The official constraints on constant expressions [6.6] are insanely strict in that they do not allow some constructs commonly used in the wild. Relax them by treating - address constants cast to different pointer type as address constants again, - address constants cast to integer type as integer constant expressions - conditional expressions whose true and false branches both yield address constants as address constants, - and conditional expressions whose condition is an address constant as an constant expression to the extent their true and false branches allow. Signed-off-by: Nicolai Stange <nicstange@xxxxxxxxx> --- evaluate.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/evaluate.c b/evaluate.c index c115e64..ee5f18f 100644 --- a/evaluate.c +++ b/evaluate.c @@ -1125,14 +1125,25 @@ static struct symbol *evaluate_conditional_expression(struct expression *expr) true = &expr->cond_true; } - expr->flags |= expr_flags_decay_consts(expr->conditional->flags & - (*true)->flags & - expr->cond_false->flags); /* + * A conditional operator yields a particular constant + * expression type only if all of its three subexpressions are + * of that type [6.6(6), 6.6(8)]. + * As an extension, relax this restriction by allowing any + * constant expression type for the condition expression. + * * A conditional operator never yields an address constant * [6.6(9)]. + * However, as an extension, if the condition is any constant + * expression, and the true and false expressions are both + * address constants, mark the result as an address constant. */ - expr->flags &= ~expr_clear_flag_mask(EXPR_FLAG_ADDR_CONST_EXPR); + if ((expr->conditional->flags & + (expr_set_flag_mask(EXPR_FLAG_ARITH_CONST_EXPR) | + expr_set_flag_mask(EXPR_FLAG_ADDR_CONST_EXPR)))) + expr->flags |= + expr_flags_decay_consts((*true)->flags & + expr->cond_false->flags); lclass = classify_type(ltype, <ype); rclass = classify_type(rtype, &rtype); @@ -2780,15 +2791,31 @@ static struct symbol *evaluate_cast(struct expression *expr) /* * Casts of integer literals to pointer type yield * address constants [6.6(9)]. + * + * As an extension, treat address constants cast to a + * different pointer type as address constants again. + * + * As another extension, treat integer constant + * expressions (in contrast to literals) cast to + * pointer type as address constants. */ if (class1 & TYPE_PTR && - (target->flags & EXPR_FLAG_INT_CONST)) { + ((target->flags & EXPR_FLAG_INT_CONST_EXPR) || + (target->flags & EXPR_FLAG_ADDR_CONST_EXPR))) { expr->flags |= expr_set_flag_mask(EXPR_FLAG_ADDR_CONST_EXPR); } } else { expr->flags |= expr_flags_decay_consts(target->flags); + + /* + * As an extension, treat address constants cast to + * integer type as an arithmetic constant. + */ + if (expr->flags & EXPR_FLAG_ADDR_CONST_EXPR) + expr->flags |= + expr_set_flag_mask(EXPR_FLAG_ARITH_CONST_EXPR); /* * Casts to numeric types never result in address * constants [6.6(9)]. -- 2.4.5 -- To unsubscribe from this list: send the line "unsubscribe linux-sparse" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html