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 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;
}
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;
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);
/**
* 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);
}
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");
}
}
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)) {
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;