evaluate: relax some constant expression rules for pointer expressions
RFC PATCH 11/13 evaluate: relax some constant expression rules for pointer expressions
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 <[email protected]>
--- evaluate.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-)
evaluate.c +32 -5
@@ -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)].
Signature · 1 line
2.4.5