static entity_t *get_entity(const symbol_t *const symbol,
namespace_tag_t namespc)
{
+ assert(namespc != NAMESPACE_INVALID);
entity_t *entity = symbol->entity;
for (; entity != NULL; entity = entity->base.symbol_next) {
if (entity->base.namespc == namespc)
}
type_t *const type = skip_typeref(expression->base.type);
- return
- is_type_integer(type) &&
- is_constant_expression(expression) &&
- !fold_constant_to_bool(expression);
+ 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;
+ }
}
/**
{
expression_t *result = parse_subexpression(PREC_CONDITIONAL);
- if (!is_constant_expression(result)) {
+ if (is_constant_expression(result) == EXPR_CLASS_VARIABLE) {
errorf(&result->base.source_position,
"expression '%E' is not constant", result);
}
*/
static bool is_initializer_constant(const expression_t *expression)
{
- return is_constant_expression(expression)
- || is_address_constant(expression);
+ return
+ is_constant_expression(expression) != EXPR_CLASS_VARIABLE ||
+ is_address_constant(expression) != EXPR_CLASS_VARIABLE;
}
/**
entity_t *entity = allocate_entity_zero(ENTITY_ENUM_VALUE);
entity->enum_value.enum_type = enum_type;
+ entity->base.namespc = NAMESPACE_NORMAL;
entity->base.symbol = token.symbol;
entity->base.source_position = token.source_position;
next_token();
static entity_t *create_error_entity(symbol_t *symbol, entity_kind_tag_t kind)
{
entity_t *entity = allocate_entity_zero(kind);
+ entity->base.namespc = NAMESPACE_NORMAL;
entity->base.source_position = *HERE;
entity->base.symbol = symbol;
if (is_declaration(entity)) {
}
rem_anchor_token(')');
expect(')', end_error);
+ } else if (!env->may_be_abstract) {
+ errorf(HERE, "declarator must have a name");
+ goto error_out;
}
break;
default:
if (env->may_be_abstract)
break;
parse_error_expected("while parsing declarator", T_IDENTIFIER, '(', NULL);
+error_out:
eat_until_anchor();
return NULL;
}
array_type->array.size_expression = size_expression;
if (size_expression != NULL) {
- if (is_constant_expression(size_expression)) {
- long const size
- = fold_constant_to_int(size_expression);
- array_type->array.size = size;
- array_type->array.size_constant = true;
- /* §6.7.5.2:1 If the expression is a constant expression, it shall
- * have a value greater than zero. */
- if (size <= 0) {
- if (size < 0 || !GNU_MODE) {
- errorf(&size_expression->base.source_position,
- "size of array must be greater than zero");
- } else if (warning.other) {
- warningf(&size_expression->base.source_position,
- "zero length arrays are a GCC extension");
+ switch (is_constant_expression(size_expression)) {
+ case EXPR_CLASS_CONSTANT: {
+ long const size = fold_constant_to_int(size_expression);
+ array_type->array.size = size;
+ array_type->array.size_constant = true;
+ /* §6.7.5.2:1 If the expression is a constant expression, it shall
+ * have a value greater than zero. */
+ if (size <= 0) {
+ if (size < 0 || !GNU_MODE) {
+ errorf(&size_expression->base.source_position,
+ "size of array must be greater than zero");
+ } else if (warning.other) {
+ warningf(&size_expression->base.source_position,
+ "zero length arrays are a GCC extension");
+ }
}
+ break;
}
- } else {
- array_type->array.is_vla = true;
+
+ case EXPR_CLASS_VARIABLE:
+ array_type->array.is_vla = true;
+ break;
+
+ case EXPR_CLASS_ERROR:
+ break;
}
}
entity_t *entity;
if (specifiers->storage_class == STORAGE_CLASS_TYPEDEF) {
entity = allocate_entity_zero(ENTITY_TYPEDEF);
+ entity->base.namespc = NAMESPACE_NORMAL;
entity->base.symbol = env.symbol;
entity->base.source_position = env.source_position;
entity->typedefe.type = orig_type;
static bool is_error_entity(entity_t *const ent)
{
if (is_declaration(ent)) {
- return is_type_valid(skip_typeref(ent->declaration.type));
+ return !is_type_valid(skip_typeref(ent->declaration.type));
} else if (ent->kind == ENTITY_TYPEDEF) {
- return is_type_valid(skip_typeref(ent->typedefe.type));
+ return !is_type_valid(skip_typeref(ent->typedefe.type));
}
return false;
}
static int determine_truth(expression_t const* const cond)
{
return
- !is_constant_expression(cond) ? 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)) {
+ if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) {
long const val = fold_constant_to_int(expr);
case_label_statement_t * defaults = NULL;
for (case_label_statement_t *i = switchs->first_case; i != NULL; i = i->next) {
bit_size = get_type_size(base_type) * 8;
}
- if (is_constant_expression(size)) {
+ if (is_constant_expression(size) == EXPR_CLASS_CONSTANT) {
long v = fold_constant_to_int(size);
const symbol_t *user_symbol = symbol == NULL ? sym_anonymous : symbol;
entity->declaration.declared_storage_class = STORAGE_CLASS_EXTERN;
entity->declaration.type = type;
entity->declaration.implicit = true;
+ entity->base.namespc = NAMESPACE_NORMAL;
entity->base.symbol = symbol;
entity->base.source_position = *source_position;
}
errorf(HERE, "unexpected token %K, expected an expression", &token);
+ eat_until_anchor();
return create_invalid_expression();
}
tp_expression->typeprop.type = orig_type;
type_t const* const type = skip_typeref(orig_type);
- char const* const wrong_type =
- GNU_MODE && is_type_atomic(type, ATOMIC_TYPE_VOID) ? NULL :
- is_type_incomplete(type) ? "incomplete" :
- type->kind == TYPE_FUNCTION ? "function designator" :
- type->kind == TYPE_BITFIELD ? "bitfield" :
- NULL;
+ char const* wrong_type = NULL;
+ if (is_type_incomplete(type)) {
+ if (!is_type_atomic(type, ATOMIC_TYPE_VOID) || !GNU_MODE)
+ wrong_type = "incomplete";
+ } else if (type->kind == TYPE_FUNCTION) {
+ if (GNU_MODE) {
+ /* function types are allowed (and return 1) */
+ if (warning.other) {
+ char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
+ warningf(&tp_expression->base.source_position,
+ "%s expression with function argument returns invalid result", what);
+ }
+ } else {
+ wrong_type = "function";
+ }
+ } else {
+ if (is_type_incomplete(type))
+ wrong_type = "incomplete";
+ }
+ if (type->kind == TYPE_BITFIELD)
+ wrong_type = "bitfield";
+
if (wrong_type != NULL) {
char const* const what = kind == EXPR_SIZEOF ? "sizeof" : "alignof";
errorf(&tp_expression->base.source_position,
{
assert(token.type == '.' || token.type == T_MINUSGREATER);
bool select_left_arrow = (token.type == T_MINUSGREATER);
+ source_position_t const pos = *HERE;
next_token();
if (token.type != T_IDENTIFIER) {
bool saw_error = false;
if (is_type_pointer(type)) {
if (!select_left_arrow) {
- errorf(HERE,
+ errorf(&pos,
"request for member '%Y' in something not a struct or union, but '%T'",
symbol, orig_type);
saw_error = true;
type_left = skip_typeref(type->pointer.points_to);
} else {
if (select_left_arrow && is_type_valid(type)) {
- errorf(HERE, "left hand side of '->' is not a pointer, but '%T'", orig_type);
+ errorf(&pos, "left hand side of '->' is not a pointer, but '%T'", orig_type);
saw_error = true;
}
type_left = type;
type_left->kind != TYPE_COMPOUND_UNION) {
if (is_type_valid(type_left) && !saw_error) {
- errorf(HERE,
+ errorf(&pos,
"request for member '%Y' in something not a struct or union, but '%T'",
symbol, type_left);
}
compound_t *compound = type_left->compound.compound;
if (!compound->complete) {
- errorf(HERE, "request for member '%Y' in incomplete type '%T'",
+ errorf(&pos, "request for member '%Y' in incomplete type '%T'",
symbol, type_left);
return create_invalid_expression();
}
type_qualifiers_t qualifiers = type_left->base.qualifiers;
- expression_t *result
- = find_create_select(HERE, addr, qualifiers, compound, symbol);
+ expression_t *result =
+ find_create_select(&pos, addr, qualifiers, compound, symbol);
if (result == NULL) {
- errorf(HERE, "'%T' has no member named '%Y'", orig_type, symbol);
+ errorf(&pos, "'%T' has no member named '%Y'", orig_type, symbol);
return create_invalid_expression();
}
/* argument must be constant */
call_argument_t *argument = call->arguments;
- if (! is_constant_expression(argument->expression)) {
+ if (is_constant_expression(argument->expression) == EXPR_CLASS_VARIABLE) {
errorf(&call->base.source_position,
"argument of '%Y' must be a constant expression",
call->function->reference.entity->base.symbol);
break;
call_argument_t *arg = call->arguments->next;
- if (arg != NULL && ! is_constant_expression(arg->expression)) {
+ if (arg != NULL && is_constant_expression(arg->expression) == EXPR_CLASS_VARIABLE) {
errorf(&call->base.source_position,
"second argument of '%Y' must be a constant expression",
call->function->reference.entity->base.symbol);
call_argument_t *locality = NULL;
if (rw != NULL) {
- if (! is_constant_expression(rw->expression)) {
+ if (is_constant_expression(rw->expression) == EXPR_CLASS_VARIABLE) {
errorf(&call->base.source_position,
"second argument of '%Y' must be a constant expression",
call->function->reference.entity->base.symbol);
locality = rw->next;
}
if (locality != NULL) {
- if (! is_constant_expression(locality->expression)) {
+ if (is_constant_expression(locality->expression) == EXPR_CLASS_VARIABLE) {
errorf(&call->base.source_position,
"third argument of '%Y' must be a constant expression",
call->function->reference.entity->base.symbol);
expression_t const *const right = expression->right;
/* The type of the right operand can be different for /= */
- if (is_type_integer(right->base.type) &&
- is_constant_expression(right) &&
+ if (is_type_integer(right->base.type) &&
+ is_constant_expression(right) == EXPR_CLASS_CONSTANT &&
!fold_constant_to_bool(right)) {
warningf(&expression->base.source_position, "division by zero");
}
type_left = promote_integer(type_left);
- if (is_constant_expression(right)) {
+ if (is_constant_expression(right) == EXPR_CLASS_CONSTANT) {
long count = fold_constant_to_int(right);
if (count < 0) {
warningf(&right->base.source_position,
static bool maybe_negative(expression_t const *const expr)
{
- return
- !is_constant_expression(expr) ||
- fold_constant_to_int(expr) < 0;
+ switch (is_constant_expression(expr)) {
+ case EXPR_CLASS_ERROR: return false;
+ case EXPR_CLASS_CONSTANT: return fold_constant_to_int(expr) < 0;
+ default: return true;
+ }
}
/**
expression_t *const expression = parse_expression();
statement->case_label.expression = expression;
- if (!is_constant_expression(expression)) {
- /* This check does not prevent the error message in all cases of an
- * prior error while parsing the expression. At least it catches the
- * common case of a mistyped enum entry. */
- if (is_type_valid(skip_typeref(expression->base.type))) {
+ expression_classification_t const expr_class = is_constant_expression(expression);
+ if (expr_class != EXPR_CLASS_CONSTANT) {
+ if (expr_class != EXPR_CLASS_ERROR) {
errorf(pos, "case label does not reduce to an integer constant");
}
statement->case_label.is_bad = true;
if (next_if(T_DOTDOTDOT)) {
expression_t *const end_range = parse_expression();
statement->case_label.end_range = end_range;
- if (!is_constant_expression(end_range)) {
- /* This check does not prevent the error message in all cases of an
- * prior error while parsing the expression. At least it catches the
- * common case of a mistyped enum entry. */
- if (is_type_valid(skip_typeref(end_range->base.type))) {
+ expression_classification_t const end_class = is_constant_expression(end_range);
+ if (end_class != EXPR_CLASS_CONSTANT) {
+ if (end_class != EXPR_CLASS_ERROR) {
errorf(pos, "case range does not reduce to an integer constant");
}
statement->case_label.is_bad = true;
eat(T___label__);
- entity_t *begin = NULL, *end = NULL;
-
+ entity_t *begin = NULL;
+ entity_t *end = NULL;
+ entity_t **anchor = &begin;
do {
if (token.type != T_IDENTIFIER) {
parse_error_expected("while parsing local label declaration",
entity->base.source_position = token.source_position;
entity->base.symbol = symbol;
- if (end != NULL)
- end->base.next = entity;
- end = entity;
- if (begin == NULL)
- begin = entity;
+ *anchor = entity;
+ anchor = &entity->base.next;
+ end = entity;
environment_push(entity);
}