This is required for strict detection of null pointer constants and VLAs.
case EXPR_CONDITIONAL: {
expression_t *const c = expression->conditional.condition;
expression_classification_t const cclass = is_constant_expression(c);
- if (cclass != EXPR_CLASS_CONSTANT)
+ if (cclass < EXPR_CLASS_CONSTANT)
return cclass;
if (fold_constant_to_bool(c)) {
array_access_expression_t const* const array_access =
&expression->array_access;
expression_classification_t const idx_class = is_constant_expression(array_access->index);
- if (idx_class != EXPR_CLASS_CONSTANT)
+ if (idx_class < EXPR_CLASS_CONSTANT)
return idx_class;
expression_classification_t const ref_addr = is_object_with_constant_address(array_access->array_ref);
expression_classification_t const ref_ptr = is_constant_pointer(array_access->array_ref);
case EXPR_ENUM_CONSTANT:
case EXPR_LITERAL_BOOLEAN:
case EXPR_LITERAL_MS_NOOP:
- return EXPR_CLASS_CONSTANT;
+ return EXPR_CLASS_INTEGER_CONSTANT;
{
type_t *type;
goto check_type;
case EXPR_LITERAL_INTEGER:
- case EXPR_LITERAL_FLOATINGPOINT:
type = skip_typeref(expression->base.type);
goto check_type;
goto check_type;
check_type:
+ return is_type_valid(type) ? EXPR_CLASS_INTEGER_CONSTANT : EXPR_CLASS_ERROR;
+ }
+
+ case EXPR_LITERAL_FLOATINGPOINT: {
+ type_t *const type = skip_typeref(expression->base.type);
return is_type_valid(type) ? EXPR_CLASS_CONSTANT : EXPR_CLASS_ERROR;
}
case EXPR_BUILTIN_CONSTANT_P: {
expression_classification_t const c = is_constant_expression(expression->builtin_constant.value);
- return c != EXPR_CLASS_ERROR ? EXPR_CLASS_CONSTANT : EXPR_CLASS_ERROR;
+ return c != EXPR_CLASS_ERROR ? EXPR_CLASS_INTEGER_CONSTANT : EXPR_CLASS_ERROR;
}
case EXPR_STRING_LITERAL:
case EXPR_UNARY_CAST: {
type_t *const type = skip_typeref(expression->base.type);
+ if (is_type_integer(type)) {
+ expression_t *const val = expression->unary.value;
+ if (is_type_arithmetic(skip_typeref(val->base.type))) {
+ return val->kind == EXPR_LITERAL_FLOATINGPOINT
+ ? EXPR_CLASS_INTEGER_CONSTANT
+ : is_constant_expression(val);
+ }
+ }
if (is_type_scalar(type))
return is_constant_expression(expression->unary.value);
if (!is_type_valid(type))
}
case EXPR_BINARY_LOGICAL_AND: {
- expression_t const *const left = expression->binary.left;
- expression_classification_t const lclass = is_constant_expression(left);
- if (lclass != EXPR_CLASS_CONSTANT)
- return lclass;
+ expression_t const *const left = expression->binary.left;
+ expression_classification_t const lcls = is_constant_expression(left);
+ if (lcls < EXPR_CLASS_CONSTANT)
+ return lcls;
+ expression_classification_t const rcls = is_constant_expression(expression->binary.right);
+ if (lcls == EXPR_CLASS_INTEGER_CONSTANT && rcls == EXPR_CLASS_INTEGER_CONSTANT)
+ return EXPR_CLASS_INTEGER_CONSTANT;
if (!fold_constant_to_bool(left))
return EXPR_CLASS_CONSTANT;
- return is_constant_expression(expression->binary.right);
+ return rcls < EXPR_CLASS_CONSTANT ? rcls : EXPR_CLASS_CONSTANT;
}
case EXPR_BINARY_LOGICAL_OR: {
- expression_t const *const left = expression->binary.left;
- expression_classification_t const lclass = is_constant_expression(left);
- if (lclass != EXPR_CLASS_CONSTANT)
- return lclass;
+ expression_t const *const left = expression->binary.left;
+ expression_classification_t const lcls = is_constant_expression(left);
+ if (lcls < EXPR_CLASS_CONSTANT)
+ return lcls;
+ expression_classification_t const rcls = is_constant_expression(expression->binary.right);
+ if (lcls == EXPR_CLASS_INTEGER_CONSTANT && rcls == EXPR_CLASS_INTEGER_CONSTANT)
+ return EXPR_CLASS_INTEGER_CONSTANT;
if (fold_constant_to_bool(left))
return EXPR_CLASS_CONSTANT;
- return is_constant_expression(expression->binary.right);
+ return rcls < EXPR_CLASS_CONSTANT ? rcls : EXPR_CLASS_CONSTANT;
}
case EXPR_COMPOUND_LITERAL:
return is_constant_initializer(expression->compound_literal.initializer);
case EXPR_CONDITIONAL: {
- expression_t *const condition = expression->conditional.condition;
- expression_classification_t const cclass = is_constant_expression(condition);
- if (cclass != EXPR_CLASS_CONSTANT)
- return cclass;
-
- if (fold_constant_to_bool(condition)) {
- expression_t const *const t = expression->conditional.true_expression;
- return t == NULL ? EXPR_CLASS_CONSTANT : is_constant_expression(t);
- } else {
- return is_constant_expression(expression->conditional.false_expression);
- }
+ expression_t *const cond = expression->conditional.condition;
+ expression_classification_t const ccls = is_constant_expression(cond);
+ if (ccls < EXPR_CLASS_CONSTANT)
+ return ccls;
+ expression_t const *const t = expression->conditional.true_expression;
+ expression_classification_t const tcls = t == NULL ? ccls : is_constant_expression(t);
+ expression_classification_t const fcls = is_constant_expression(expression->conditional.false_expression);
+ if (ccls == EXPR_CLASS_INTEGER_CONSTANT &&
+ tcls == EXPR_CLASS_INTEGER_CONSTANT &&
+ fcls == EXPR_CLASS_INTEGER_CONSTANT)
+ return EXPR_CLASS_INTEGER_CONSTANT;
+ expression_classification_t const cls = fold_constant_to_bool(cond) ? tcls : fcls;
+ return cls < EXPR_CLASS_CONSTANT ? cls : EXPR_CLASS_CONSTANT;
}
case EXPR_ERROR:
typedef enum expression_classification_t {
EXPR_CLASS_VARIABLE,
EXPR_CLASS_ERROR,
- EXPR_CLASS_CONSTANT
+ EXPR_CLASS_CONSTANT,
+ EXPR_CLASS_INTEGER_CONSTANT
} expression_classification_t;
/**
}
expression_t *con = NULL;
- if (is_local_variable(op1) && is_constant_expression(op2) == EXPR_CLASS_CONSTANT) {
+ if (is_local_variable(op1) && is_constant_expression(op2) != EXPR_CLASS_VARIABLE) {
var = op1->reference.entity;
con = op2;
- } else if (is_constant_expression(op1) == EXPR_CLASS_CONSTANT && is_local_variable(op2)) {
+ } else if (is_constant_expression(op1) != EXPR_CLASS_VARIABLE && is_local_variable(op2)) {
relation = get_inversed_relation(relation);
var = op2->reference.entity;
con = op1;
/* set branch prediction info based on __builtin_expect */
if (is_builtin_expect(expr) && is_Cond(cond)) {
call_argument_t *const argument = expr->call.arguments->next;
- if (is_constant_expression(argument->expression) == EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(argument->expression) != EXPR_CLASS_VARIABLE) {
bool const cnst = fold_constant_to_bool(argument->expression);
cond_jmp_predicate const pred = cnst ? COND_JMP_PRED_TRUE : COND_JMP_PRED_FALSE;
set_Cond_jmp_pred(cond, pred);
type_t *type = expression->type;
initializer_t *initializer = expression->initializer;
- if (expression->global_scope ||
- ((type->base.qualifiers & TYPE_QUALIFIER_CONST)
- && is_constant_initializer(initializer) == EXPR_CLASS_CONSTANT)) {
+ if (expression->global_scope || (
+ type->base.qualifiers & TYPE_QUALIFIER_CONST &&
+ is_constant_initializer(initializer) != EXPR_CLASS_VARIABLE
+ )) {
ir_entity *entity = create_initializer_entity(dbgi, initializer, type);
return create_symconst(dbgi, entity);
} else {
ir_tarval *fold_constant_to_tarval(const expression_t *expression)
{
- assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
+ assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT);
bool constant_folding_old = constant_folding;
constant_folding = true;
static complex_constant fold_complex_constant(const expression_t *expression)
{
- assert(is_constant_expression(expression) == EXPR_CLASS_CONSTANT);
+ assert(is_constant_expression(expression) >= EXPR_CLASS_CONSTANT);
bool constant_folding_old = constant_folding;
constant_folding = true;
const builtin_constant_expression_t *expression)
{
ir_mode *const mode = get_ir_mode_storage(expression->base.type);
- bool const v = is_constant_expression(expression->value) == EXPR_CLASS_CONSTANT;
+ bool const v = is_constant_expression(expression->value) != EXPR_CLASS_VARIABLE;
return create_Const_from_bool(mode, v);
}
expression_t *const cond = statement->condition;
/* Avoid an explicit body block in case of do ... while (0);. */
- if (is_constant_expression(cond) == EXPR_CLASS_CONSTANT && !fold_constant_to_bool(cond)) {
+ if (is_constant_expression(cond) != EXPR_CLASS_VARIABLE && !fold_constant_to_bool(cond)) {
/* do ... while (0);. */
statement_to_firm(statement->body);
jump_to_target(&continue_target);
/* Create the condition. */
expression_t *const cond = statement->condition;
- if (cond && (is_constant_expression(cond) != EXPR_CLASS_CONSTANT || !fold_constant_to_bool(cond))) {
+ if (cond && (is_constant_expression(cond) == EXPR_CLASS_VARIABLE || !fold_constant_to_bool(cond))) {
jump_target body_target;
init_jump_target(&body_target, NULL);
expression_to_control_flow(cond, &body_target, &break_target);
expression = expression->unary.value;
}
- type_t *const type = skip_typeref(expression->base.type);
- if (!is_type_integer(type))
- return false;
switch (is_constant_expression(expression)) {
- case EXPR_CLASS_ERROR: return true;
- case EXPR_CLASS_CONSTANT: return !fold_constant_to_bool(expression);
- default: return false;
+ case EXPR_CLASS_VARIABLE: return false;
+ case EXPR_CLASS_ERROR: return true;
+ case EXPR_CLASS_CONSTANT: return false;
+ case EXPR_CLASS_INTEGER_CONSTANT: return !fold_constant_to_bool(expression);
}
+ panic("invalid expression classification");
}
/**
}
} else {
expression_t *array_index = designator->array_index;
- if (is_constant_expression(array_index) != EXPR_CLASS_CONSTANT)
+ if (is_constant_expression(array_index) < EXPR_CLASS_CONSTANT)
return true;
if (!is_type_array(type)) {
if (size_expression != NULL) {
switch (is_constant_expression(size_expression)) {
- case EXPR_CLASS_CONSTANT: {
+ case EXPR_CLASS_INTEGER_CONSTANT: {
long const size = fold_constant_to_int(size_expression);
array_type->array.size = size;
array_type->array.size_constant = true;
break;
}
+ case EXPR_CLASS_CONSTANT:
case EXPR_CLASS_VARIABLE:
array_type->array.is_vla = true;
break;
static int determine_truth(expression_t const* const cond)
{
return
- is_constant_expression(cond) != EXPR_CLASS_CONSTANT ? 0 :
- fold_constant_to_bool(cond) ? 1 :
+ is_constant_expression(cond) < EXPR_CLASS_CONSTANT ? 0 :
+ fold_constant_to_bool(cond) ? 1 :
-1;
}
if (!expression_returns(expr))
return;
- if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(expr) >= EXPR_CLASS_CONSTANT) {
ir_tarval *const val = fold_constant_to_tarval(expr);
case_label_statement_t * defaults = NULL;
for (case_label_statement_t *i = switchs->first_case; i != NULL; i = i->next) {
type);
}
- if (is_constant_expression(size) != EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(size) < EXPR_CLASS_CONSTANT) {
/* error already reported by parse_constant_expression */
size_long = get_type_size(type) * 8;
} else {
expression_t const *const right = expression->right;
/* The type of the right operand can be different for /= */
if (is_type_integer(skip_typeref(right->base.type)) &&
- is_constant_expression(right) == EXPR_CLASS_CONSTANT &&
+ is_constant_expression(right) >= EXPR_CLASS_CONSTANT &&
!fold_constant_to_bool(right)) {
position_t const *const pos = &expression->base.pos;
warningf(WARN_DIV_BY_ZERO, pos, "division by zero");
type_left = promote_integer(type_left);
- if (is_constant_expression(right) == EXPR_CLASS_CONSTANT) {
+ if (is_constant_expression(right) >= EXPR_CLASS_CONSTANT) {
position_t const *const pos = &right->base.pos;
long const count = fold_constant_to_int(right);
if (count < 0) {
static bool maybe_negative(expression_t const *const expr)
{
switch (is_constant_expression(expr)) {
- case EXPR_CLASS_ERROR: return false;
- case EXPR_CLASS_CONSTANT: return constant_is_negative(expr);
- default: return true;
+ case EXPR_CLASS_VARIABLE: return true;
+ case EXPR_CLASS_ERROR: return false;
+ case EXPR_CLASS_CONSTANT:
+ case EXPR_CLASS_INTEGER_CONSTANT: return constant_is_negative(expr);
}
+ panic("invalid expression classification");
}
static void warn_comparison(position_t const *const pos, expression_t const *const expr, expression_t const *const other)
statement->case_label.expression = expression;
expression_classification_t const expr_class = is_constant_expression(expression);
- if (expr_class != EXPR_CLASS_CONSTANT) {
+ if (expr_class < EXPR_CLASS_CONSTANT) {
if (expr_class != EXPR_CLASS_ERROR) {
errorf(pos, "case label does not reduce to an integer constant");
}
end_range = create_implicit_cast(end_range, type);
statement->case_label.end_range = end_range;
expression_classification_t const end_class = is_constant_expression(end_range);
- if (end_class != EXPR_CLASS_CONSTANT) {
+ if (end_class < EXPR_CLASS_CONSTANT) {
if (end_class != EXPR_CLASS_ERROR) {
errorf(pos, "case range does not reduce to an integer constant");
}