static statement_t *current_loop = NULL;
static statement_t *current_parent = NULL;
static ms_try_statement_t *current_try = NULL;
-static linkage_kind_t current_linkage = LINKAGE_INVALID;
+static linkage_kind_t current_linkage;
static goto_statement_t *goto_first = NULL;
static goto_statement_t **goto_anchor = NULL;
static label_statement_t *label_first = NULL;
static size_t get_statement_struct_size(statement_kind_t kind)
{
static const size_t sizes[] = {
- [STATEMENT_INVALID] = sizeof(invalid_statement_t),
- [STATEMENT_EMPTY] = sizeof(empty_statement_t),
+ [STATEMENT_ERROR] = sizeof(statement_base_t),
+ [STATEMENT_EMPTY] = sizeof(statement_base_t),
[STATEMENT_COMPOUND] = sizeof(compound_statement_t),
[STATEMENT_RETURN] = sizeof(return_statement_t),
[STATEMENT_DECLARATION] = sizeof(declaration_statement_t),
static size_t get_expression_struct_size(expression_kind_t kind)
{
static const size_t sizes[] = {
- [EXPR_INVALID] = sizeof(expression_base_t),
+ [EXPR_ERROR] = sizeof(expression_base_t),
[EXPR_REFERENCE] = sizeof(reference_expression_t),
[EXPR_REFERENCE_ENUM_VALUE] = sizeof(reference_expression_t),
[EXPR_LITERAL_BOOLEAN] = sizeof(literal_expression_t),
* Creates a new invalid expression at the source position
* of the current token.
*/
-static expression_t *create_invalid_expression(void)
+static expression_t *create_error_expression(void)
{
- return allocate_expression_zero(EXPR_INVALID);
+ expression_t *expression = allocate_expression_zero(EXPR_ERROR);
+ expression->base.type = type_error_type;
+ return expression;
}
/**
* Creates a new invalid statement.
*/
-static statement_t *create_invalid_statement(void)
+static statement_t *create_error_statement(void)
{
- return allocate_statement_zero(STATEMENT_INVALID);
+ return allocate_statement_zero(STATEMENT_ERROR);
}
/**
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 ((namespace_tag_t)entity->base.namespc == namespc)
{
symbol_t *symbol = entity->base.symbol;
entity_namespace_t namespc = entity->base.namespc;
- assert(namespc != NAMESPACE_INVALID);
+ assert(namespc != 0);
/* replace/add entity into entity list of the symbol */
entity_t **anchor;
stack_pop_to(&label_stack, new_top);
}
-static int get_akind_rank(atomic_type_kind_t akind)
+static atomic_type_kind_t get_akind(const type_t *type)
{
- return (int) akind;
-}
-
-/**
- * Return the type rank for an atomic type.
- */
-static int get_rank(const type_t *type)
-{
- assert(!is_typeref(type));
- if (type->kind == TYPE_ENUM)
- return get_akind_rank(type->enumt.akind);
-
- assert(type->kind == TYPE_ATOMIC);
- return get_akind_rank(type->atomic.akind);
+ assert(type->kind == TYPE_ATOMIC || type->kind == TYPE_COMPLEX
+ || type->kind == TYPE_IMAGINARY || type->kind == TYPE_ENUM);
+ return type->atomic.akind;
}
/**
*/
static type_t *promote_integer(type_t *type)
{
- if (get_rank(type) < get_akind_rank(ATOMIC_TYPE_INT))
+ if (get_akind_rank(get_akind(type)) < get_akind_rank(ATOMIC_TYPE_INT))
type = type_int;
return type;
ent = determine_lhs_ent(ref, lhs_ent);
lhs_ent = ent;
} else {
- mark_vars_read(expr->select.compound, lhs_ent);
+ mark_vars_read(ref, lhs_ent);
}
mark_vars_read(expr->array_access.index, lhs_ent);
return ent;
}
case EXPR_SELECT: {
- if (is_type_compound(skip_typeref(expr->base.type))) {
+ mark_vars_read(expr->select.compound, lhs_ent);
+ if (is_type_compound(skip_typeref(expr->base.type)))
return determine_lhs_ent(expr->select.compound, lhs_ent);
- } else {
- mark_vars_read(expr->select.compound, lhs_ent);
- return NULL;
- }
+ return NULL;
}
case EXPR_UNARY_DEREFERENCE: {
return;
case EXPR_ARRAY_ACCESS: {
+ mark_vars_read(expr->array_access.index, lhs_ent);
expression_t *const ref = expr->array_access.array_ref;
+ if (!is_type_array(skip_typeref(revert_automatic_type_conversion(ref)))) {
+ if (lhs_ent == ENT_ANY)
+ lhs_ent = NULL;
+ }
mark_vars_read(ref, lhs_ent);
- lhs_ent = determine_lhs_ent(ref, lhs_ent);
- mark_vars_read(expr->array_access.index, lhs_ent);
return;
}
return;
EXPR_LITERAL_CASES
- case EXPR_INVALID:
+ case EXPR_ERROR:
case EXPR_STRING_LITERAL:
case EXPR_WIDE_STRING_LITERAL:
case EXPR_COMPOUND_LITERAL: // TODO init?
entity->base.parent_scope = current_scope;
}
- type_t *const type = allocate_type_zero(TYPE_ENUM);
- type->enumt.enume = &entity->enume;
- type->enumt.akind = ATOMIC_TYPE_INT;
+ type_t *const type = allocate_type_zero(TYPE_ENUM);
+ type->enumt.enume = &entity->enume;
+ type->enumt.base.akind = ATOMIC_TYPE_INT;
if (token.kind == '{') {
if (symbol != NULL) {
}
if (type_specifiers & SPECIFIER_COMPLEX) {
- type = allocate_type_zero(TYPE_COMPLEX);
- type->complex.akind = atomic_type;
+ type = allocate_type_zero(TYPE_COMPLEX);
} else if (type_specifiers & SPECIFIER_IMAGINARY) {
- type = allocate_type_zero(TYPE_IMAGINARY);
- type->imaginary.akind = atomic_type;
+ type = allocate_type_zero(TYPE_IMAGINARY);
} else {
- type = allocate_type_zero(TYPE_ATOMIC);
- type->atomic.akind = atomic_type;
+ type = allocate_type_zero(TYPE_ATOMIC);
}
+ type->atomic.akind = atomic_type;
newtype = true;
} else if (type_specifiers != 0) {
errorf(&specifiers->source_position, "multiple datatypes in declaration");
}
typedef enum construct_type_kind_t {
- CONSTRUCT_INVALID,
- CONSTRUCT_POINTER,
+ CONSTRUCT_POINTER = 1,
CONSTRUCT_REFERENCE,
CONSTRUCT_FUNCTION,
CONSTRUCT_ARRAY
for (; iter != NULL; iter = iter->base.next) {
source_position_t const* const pos = &iter->base.pos;
switch (iter->kind) {
- case CONSTRUCT_INVALID:
- break;
case CONSTRUCT_FUNCTION: {
construct_function_type_t *function = &iter->function;
type_t *function_type = function->function_type;
case EXPR_BUILTIN_CONSTANT_P:
case EXPR_BUILTIN_TYPES_COMPATIBLE_P:
case EXPR_OFFSETOF:
- case EXPR_INVALID:
+ case EXPR_ERROR:
return true;
case EXPR_STATEMENT: {
statement_t *last = stmt;
statement_t *next;
switch (stmt->kind) {
- case STATEMENT_INVALID:
+ case STATEMENT_ERROR:
case STATEMENT_EMPTY:
case STATEMENT_ASM:
next = stmt->base.next;
}
switch (next->kind) {
- case STATEMENT_INVALID:
+ case STATEMENT_ERROR:
case STATEMENT_EMPTY:
case STATEMENT_DECLARATION:
case STATEMENT_EXPRESSION:
}
next_token();
- return create_invalid_expression();
+ return create_error_expression();
}
static type_t *get_string_type(void)
if (entity == NULL) {
if (!strict_mode && token.kind == '(') {
/* an implicitly declared function */
- warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos, "implicit declaration of function '%Y'", symbol);
+ warningf(WARN_IMPLICIT_FUNCTION_DECLARATION, &pos,
+ "implicit declaration of function '%Y'", symbol);
entity = create_implicit_function(symbol, &pos);
} else {
errorf(&pos, "unknown identifier '%Y' found.", symbol);
return cast;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
descend_into_subtype(&path);
if (!walk_designator(&path, designator, true)) {
- return create_invalid_expression();
+ return create_error_expression();
}
DEL_ARR_F(path.path);
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
}
expect(')', end_error);
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
expression->base.type = type_void;
return expression;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
eat(T_ANDAND);
if (token.kind != T_IDENTIFIER) {
parse_error_expected("while parsing label address", T_IDENTIFIER, NULL);
- return create_invalid_expression();
+ return create_error_expression();
}
label_t *const label = get_label();
parse_declaration_specifiers(&specifiers);
type_t const *const type = parse_abstract_declarator(specifiers.type);
errorf(&pos, "encountered type '%T' while parsing expression", type);
- return create_invalid_expression();
+ return create_error_expression();
}
}
errorf(HERE, "unexpected token %K, expected an expression", &token);
eat_until_anchor();
- return create_invalid_expression();
+ return create_error_expression();
}
static expression_t *parse_array_expression(expression_t *left)
if (token.kind != T_IDENTIFIER) {
parse_error_expected("while parsing select", T_IDENTIFIER, NULL);
- return create_invalid_expression();
+ return create_error_expression();
}
symbol_t *symbol = token.identifier.symbol;
next_token();
"request for member '%Y' in something not a struct or union, but '%T'",
symbol, type_left);
}
- return create_invalid_expression();
+ return create_error_expression();
}
compound_t *compound = type_left->compound.compound;
if (!compound->complete) {
errorf(&pos, "request for member '%Y' in incomplete type '%T'",
symbol, type_left);
- return create_invalid_expression();
+ return create_error_expression();
}
type_qualifiers_t qualifiers = type_left->base.qualifiers;
if (result == NULL) {
errorf(&pos, "'%T' has no member named '%Y'", orig_type, symbol);
- return create_invalid_expression();
+ return create_error_expression();
}
return result;
/**
* Handle the semantic restrictions of builtin calls
*/
-static void handle_builtin_argument_restrictions(call_expression_t *call) {
- switch (call->function->reference.entity->function.btk) {
- case bk_gnu_builtin_return_address:
- case bk_gnu_builtin_frame_address: {
+static void handle_builtin_argument_restrictions(call_expression_t *call)
+{
+ entity_t *entity = call->function->reference.entity;
+ switch (entity->function.btk) {
+ case BUILTIN_FIRM:
+ switch (entity->function.b.firm_builtin_kind) {
+ case ir_bk_return_address:
+ case ir_bk_frame_address: {
/* argument must be constant */
call_argument_t *argument = call->arguments;
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;
- }
- case bk_gnu_builtin_object_size:
- if (call->arguments == NULL)
- break;
-
- call_argument_t *arg = call->arguments->next;
- 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",
+ "argument of '%Y' must be a constant expression",
call->function->reference.entity->base.symbol);
}
break;
- case bk_gnu_builtin_prefetch:
+ }
+ case ir_bk_prefetch:
/* second and third argument must be constant if existent */
if (call->arguments == NULL)
break;
if (rw != NULL) {
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);
+ "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) == EXPR_CLASS_VARIABLE) {
errorf(&call->base.source_position,
- "third argument of '%Y' must be a constant expression",
- call->function->reference.entity->base.symbol);
+ "third argument of '%Y' must be a constant expression",
+ call->function->reference.entity->base.symbol);
}
locality = rw->next;
}
break;
default:
break;
+ }
+
+ case BUILTIN_OBJECT_SIZE:
+ if (call->arguments == NULL)
+ break;
+
+ call_argument_t *arg = call->arguments->next;
+ 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);
+ }
+ break;
+ default:
+ break;
}
}
if (expression->kind == EXPR_REFERENCE) {
reference_expression_t *reference = &expression->reference;
if (reference->entity->kind == ENTITY_FUNCTION &&
- reference->entity->function.btk != bk_none)
+ reference->entity->function.btk != BUILTIN_NONE)
handle_builtin_argument_restrictions(call);
}
return result;
end_error:
- return create_invalid_expression();
+ return create_error_expression();
}
/**
expression->base.type = orig_type;
}
+static void promote_unary_int_expr(unary_expression_t *const expr, type_t *const type)
+{
+ type_t *const res_type = promote_integer(type);
+ expr->base.type = res_type;
+ expr->value = create_implicit_cast(expr->value, res_type);
+}
+
static void semantic_unexpr_arithmetic(unary_expression_t *expression)
{
type_t *const orig_type = expression->value->base.type;
"operation needs an arithmetic type");
}
return;
+ } else if (is_type_integer(type)) {
+ promote_unary_int_expr(expression, type);
+ } else {
+ expression->base.type = orig_type;
}
-
- expression->base.type = orig_type;
}
static void semantic_unexpr_plus(unary_expression_t *expression)
return;
}
- expression->base.type = orig_type;
+ promote_unary_int_expr(expression, type);
}
static void semantic_dereference(unary_expression_t *expression)
if (type_left == type_right)
return type_left;
- bool const signed_left = is_type_signed(type_left);
- bool const signed_right = is_type_signed(type_right);
- int const rank_left = get_rank(type_left);
- int const rank_right = get_rank(type_right);
+ bool const signed_left = is_type_signed(type_left);
+ bool const signed_right = is_type_signed(type_right);
+ unsigned const rank_left = get_akind_rank(get_akind(type_left));
+ unsigned const rank_right = get_akind_rank(get_akind(type_right));
if (signed_left == signed_right)
return rank_left >= rank_right ? type_left : type_right;
- int s_rank;
- int u_rank;
+ unsigned s_rank;
+ unsigned u_rank;
+ atomic_type_kind_t s_akind;
+ atomic_type_kind_t u_akind;
type_t *s_type;
type_t *u_type;
if (signed_left) {
- s_rank = rank_left;
s_type = type_left;
- u_rank = rank_right;
u_type = type_right;
} else {
- s_rank = rank_right;
s_type = type_right;
- u_rank = rank_left;
u_type = type_left;
}
+ s_akind = get_akind(s_type);
+ u_akind = get_akind(u_type);
+ s_rank = get_akind_rank(s_akind);
+ u_rank = get_akind_rank(u_akind);
if (u_rank >= s_rank)
return u_type;
- /* casting rank to atomic_type_kind is a bit hacky, but makes things
- * easier here... */
- if (get_atomic_type_size((atomic_type_kind_t) s_rank)
- > get_atomic_type_size((atomic_type_kind_t) u_rank))
+ if (get_atomic_type_size(s_akind) > get_atomic_type_size(u_akind))
return s_type;
- switch (s_rank) {
- case ATOMIC_TYPE_INT: return type_unsigned_int;
- case ATOMIC_TYPE_LONG: return type_unsigned_long;
- case ATOMIC_TYPE_LONGLONG: return type_unsigned_long_long;
+ switch (s_akind) {
+ case ATOMIC_TYPE_INT: return type_unsigned_int;
+ case ATOMIC_TYPE_LONG: return type_unsigned_long;
+ case ATOMIC_TYPE_LONGLONG: return type_unsigned_long_long;
- default: panic("invalid atomic type");
+ default: panic("invalid atomic type");
}
}
static bool expression_has_effect(const expression_t *const expr)
{
switch (expr->kind) {
- case EXPR_INVALID: return true; /* do NOT warn */
+ case EXPR_ERROR: return true; /* do NOT warn */
case EXPR_REFERENCE: return false;
case EXPR_REFERENCE_ENUM_VALUE: return false;
case EXPR_LABEL_ADDRESS: return false;
return statement;
end_error:
- return create_invalid_statement();
+ return create_error_statement();
}
static statement_t *parse_label_inner_statement(statement_t const *const label, char const *const label_kind)
switch (token.kind) {
case '}':
errorf(&label->base.source_position, "%s at end of compound statement", label_kind);
- inner_stmt = create_invalid_statement();
+ inner_stmt = create_error_statement();
break;
case ';':
type_t * type = skip_typeref(expr->base.type);
if (is_type_integer(type)) {
type = promote_integer(type);
- if (get_rank(type) >= get_akind_rank(ATOMIC_TYPE_LONG)) {
+ if (get_akind_rank(get_akind(type)) >= get_akind_rank(ATOMIC_TYPE_LONG)) {
warningf(WARN_TRADITIONAL, &expr->base.source_position, "'%T' switch expression not converted to '%T' in ISO C", type, type_int);
}
} else if (is_type_valid(type)) {
return statement;
end_error:
POP_PARENT();
- return create_invalid_statement();
+ return create_error_statement();
}
static statement_t *parse_loop_body(statement_t *const loop)
return statement;
end_error:
POP_PARENT();
- return create_invalid_statement();
+ return create_error_statement();
}
/**
return statement;
end_error:
POP_PARENT();
- return create_invalid_statement();
+ return create_error_statement();
}
/**
/* fallthrough */
end_error1:
- return create_invalid_statement();
+ return create_error_statement();
}
/**
else
parse_error_expected("while parsing goto", T_IDENTIFIER, NULL);
eat_until_anchor();
- return create_invalid_statement();
+ return create_error_statement();
}
/* remember the goto's in a list for later checking */
statement->ms_try.final_statement = parse_compound_statement(false);
} else {
parse_error_expected("while parsing __try statement", T___except, T___finally, NULL);
- return create_invalid_statement();
+ return create_error_statement();
}
return statement;
end_error:
- return create_invalid_statement();
+ return create_error_statement();
}
static statement_t *parse_empty_statement(void)
default:
errorf(HERE, "unexpected token %K while parsing statement", &token);
- statement = create_invalid_statement();
+ statement = create_error_statement();
if (!at_anchor())
next_token();
break;
break;
}
statement_t *sub_statement = intern_parse_statement();
- if (is_invalid_statement(sub_statement)) {
+ if (sub_statement->kind == STATEMENT_ERROR) {
/* an error occurred. if we are at an anchor, return */
if (at_anchor())
goto end_error;
new_linkage = LINKAGE_CXX;
} else {
errorf(&pos, "linkage string \"%s\" not recognized", linkage);
- new_linkage = LINKAGE_INVALID;
+ new_linkage = LINKAGE_C;
}
current_linkage = new_linkage;