#include "parser.h"
#include "diagnostic.h"
#include "format_check.h"
-#include "lexer.h"
+#include "preprocessor.h"
#include "symbol_t.h"
#include "token_t.h"
#include "types.h"
#include "walk.h"
#include "warning.h"
#include "printer.h"
+#include "ast2firm.h"
#include "adt/bitfiddle.h"
#include "adt/error.h"
#include "adt/array.h"
storage_class_t storage_class;
unsigned char alignment; /**< Alignment, 0 if not set. */
bool is_inline : 1;
- bool thread_local : 1; /**< GCC __thread */
+ bool thread_local : 1;
attribute_t *attributes; /**< list of attributes */
type_t *type;
};
case T_static: \
case T_auto: \
case T_register: \
- case T___thread:
+ case T__Thread_local:
#define TYPE_QUALIFIERS \
case T_const: \
case T_MINUSMINUS: \
case T_PLUSPLUS: \
case T_STRING_LITERAL: \
+ case T__Alignof: \
case T___FUNCDNAME__: \
case T___FUNCSIG__: \
case T___PRETTY_FUNCTION__: \
- case T___alignof__: \
case T___builtin_classify_type: \
case T___builtin_constant_p: \
case T___builtin_isgreater: \
[STATEMENT_GOTO] = sizeof(goto_statement_t),
[STATEMENT_LABEL] = sizeof(label_statement_t),
[STATEMENT_CASE_LABEL] = sizeof(case_label_statement_t),
- [STATEMENT_WHILE] = sizeof(while_statement_t),
[STATEMENT_DO_WHILE] = sizeof(do_while_statement_t),
[STATEMENT_FOR] = sizeof(for_statement_t),
[STATEMENT_ASM] = sizeof(asm_statement_t),
[EXPR_LITERAL_INTEGER] = sizeof(literal_expression_t),
[EXPR_LITERAL_FLOATINGPOINT] = sizeof(literal_expression_t),
[EXPR_LITERAL_CHARACTER] = sizeof(string_literal_expression_t),
+ [EXPR_LITERAL_MS_NOOP] = sizeof(literal_expression_t),
[EXPR_STRING_LITERAL] = sizeof(string_literal_expression_t),
[EXPR_COMPOUND_LITERAL] = sizeof(compound_literal_expression_t),
[EXPR_CALL] = sizeof(call_expression_t),
static inline void next_token(void)
{
token = lookahead_buffer[lookahead_bufpos];
- lookahead_buffer[lookahead_bufpos] = lexer_token;
- lexer_next_token();
+ lookahead_buffer[lookahead_bufpos] = pp_token;
+ next_preprocessing_token();
lookahead_bufpos = (lookahead_bufpos + 1) % MAX_LOOKAHEAD;
char const *const name = symbol->string;
for (kind = ATTRIBUTE_GNU_FIRST;; ++kind) {
if (kind > ATTRIBUTE_GNU_LAST) {
+ /* special case for "__const" */
+ if (token.kind == T_const) {
+ kind = ATTRIBUTE_GNU_CONST;
+ break;
+ }
+
warningf(WARN_ATTRIBUTE, HERE, "unknown attribute '%s' ignored", name);
/* TODO: we should still save the attribute in the list... */
kind = ATTRIBUTE_UNKNOWN;
return create_empty_initializer();
}
+ initializer_t *result = NULL;
+
type_t *orig_type = path->top_type;
type_t *type = NULL;
/* handle { "string" } special case */
if (expression->kind == EXPR_STRING_LITERAL && outer_type != NULL) {
- sub = initializer_from_expression(outer_type, expression);
- if (sub != NULL) {
+ result = initializer_from_expression(outer_type, expression);
+ if (result != NULL) {
next_if(',');
if (token.kind != '}') {
- warningf(WARN_OTHER, HERE, "excessive elements in initializer for type '%T'", orig_type);
+ warningf(WARN_OTHER, HERE, "excessive elements in initializer for type '%T'", outer_type);
}
/* TODO: eat , ... */
- return sub;
+ goto out;
}
}
ARR_APP1(initializer_t*, initializers, sub);
error_parse_next:
- if (token.kind == '}') {
+ if (!next_if(','))
break;
- }
- add_anchor_token('}');
- expect(',');
- rem_anchor_token('}');
if (token.kind == '}') {
break;
}
size_t len = ARR_LEN(initializers);
size_t size = sizeof(initializer_list_t) + len * sizeof(initializers[0]);
- initializer_t *result = allocate_ast_zero(size);
- result->kind = INITIALIZER_LIST;
- result->list.len = len;
+ result = allocate_ast_zero(size);
+ result->kind = INITIALIZER_LIST;
+ result->list.len = len;
memcpy(&result->list.initializers, initializers,
len * sizeof(initializers[0]));
-
- DEL_ARR_F(initializers);
- ascend_to(path, top_path_level+1);
-
- return result;
+ goto out;
end_error:
skip_initializers();
+out:
DEL_ARR_F(initializers);
ascend_to(path, top_path_level+1);
- return NULL;
+ return result;
}
static expression_t *make_size_literal(size_t value)
}
if (attributes != NULL) {
+ entity->compound.attributes = attributes;
handle_entity_attributes(attributes, entity);
}
= parse_microsoft_extended_decl_modifier(specifiers->attributes);
break;
- case T___thread:
+ case T__Thread_local:
if (specifiers->thread_local) {
- errorf(HERE, "duplicate '__thread'");
+ errorf(HERE, "duplicate %K", &token);
} else {
specifiers->thread_local = true;
check_thread_storage_class:
case STORAGE_CLASS_REGISTER: wrong = "register"; goto wrong_thread_storage_class;
case STORAGE_CLASS_TYPEDEF: wrong = "typedef"; goto wrong_thread_storage_class;
wrong_thread_storage_class:
- errorf(HERE, "'__thread' used with '%s'", wrong);
+ errorf(HERE, "%K used with '%s'", &token, wrong);
break;
}
}
warn_unused_entity(WARN_UNUSED_PARAMETER, scope->entities, NULL);
}
if (is_warn_on(WARN_UNUSED_VARIABLE)) {
- walk_statements(current_function->statement, check_unused_variables,
- NULL);
+ walk_statements(current_function->body, check_unused_variables, NULL);
}
}
return;
if (is_constant_expression(expr) == EXPR_CLASS_CONSTANT) {
- long const val = fold_constant_to_int(expr);
+ 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) {
if (i->expression == NULL) {
continue;
}
- if (i->first_case <= val && val <= i->last_case) {
+ if (i->first_case == val || i->last_case == val ||
+ ((tarval_cmp(i->first_case, val) & ir_relation_less_equal)
+ && (tarval_cmp(val, i->last_case) & ir_relation_less_equal))) {
check_reachable((statement_t*)i);
return;
}
next = parent;
switch (parent->kind) {
- case STATEMENT_WHILE: goto continue_while;
case STATEMENT_DO_WHILE: goto continue_do_while;
case STATEMENT_FOR: goto continue_for;
switch (parent->kind) {
case STATEMENT_SWITCH:
- case STATEMENT_WHILE:
case STATEMENT_DO_WHILE:
case STATEMENT_FOR:
last = parent;
next = stmt->case_label.statement;
break;
- case STATEMENT_WHILE: {
- while_statement_t const *const whiles = &stmt->whiles;
- expression_t const *const cond = whiles->condition;
-
- if (!expression_returns(cond))
- return;
-
- int const val = determine_truth(cond);
-
- if (val >= 0)
- check_reachable(whiles->body);
-
- if (val > 0)
- return;
-
- next = stmt->base.next;
- break;
- }
-
case STATEMENT_DO_WHILE:
next = stmt->do_while.body;
break;
next = next->base.next;
break;
- case STATEMENT_WHILE: {
-continue_while:
- if (next->base.reachable)
- return;
- next->base.reachable = true;
-
- while_statement_t const *const whiles = &next->whiles;
- expression_t const *const cond = whiles->condition;
-
- if (!expression_returns(cond))
- return;
-
- int const val = determine_truth(cond);
-
- if (val >= 0)
- check_reachable(whiles->body);
-
- if (val > 0)
- return;
-
- last = next;
- next = next->base.next;
- break;
- }
-
case STATEMENT_DO_WHILE: {
continue_do_while:
if (next->base.reachable)
environment_push(parameter);
}
- if (function->statement != NULL) {
+ if (function->body != NULL) {
parser_error_multiple_definition(entity, HERE);
eat_block();
} else {
label_anchor = &label_first;
statement_t *const body = parse_compound_statement(false);
- function->statement = body;
+ function->body = body;
first_err = true;
check_labels();
check_declarations();
expression_t *tp_expression = allocate_expression_zero(kind);
tp_expression->base.type = type_size_t;
- eat(kind == EXPR_SIZEOF ? T_sizeof : T___alignof__);
+ eat(kind == EXPR_SIZEOF ? T_sizeof : T__Alignof);
type_t *orig_type;
expression_t *expression;
"third argument of '%Y' must be a constant expression",
call->function->reference.entity->base.symbol);
}
- locality = rw->next;
}
break;
default:
register_expression_parser(parse_EXPR_UNARY_PREFIX_INCREMENT, T_PLUSPLUS);
register_expression_parser(parse_EXPR_UNARY_PREFIX_DECREMENT, T_MINUSMINUS);
register_expression_parser(parse_sizeof, T_sizeof);
- register_expression_parser(parse_alignof, T___alignof__);
+ register_expression_parser(parse_alignof, T__Alignof);
register_expression_parser(parse_extension, T___extension__);
register_expression_parser(parse_builtin_classify_type, T___builtin_classify_type);
register_expression_parser(parse_delete, T_delete);
}
statement->case_label.is_bad = true;
} else {
- long const val = fold_constant_to_int(expression);
+ ir_tarval *val = fold_constant_to_tarval(expression);
statement->case_label.first_case = val;
statement->case_label.last_case = val;
}
}
statement->case_label.is_bad = true;
} else {
- long const val = fold_constant_to_int(end_range);
+ ir_tarval *val = fold_constant_to_tarval(end_range);
statement->case_label.last_case = val;
- if (val < statement->case_label.first_case) {
+ if (tarval_cmp(val, statement->case_label.first_case)
+ == ir_relation_less) {
statement->case_label.is_empty_range = true;
warningf(WARN_OTHER, pos, "empty range specified");
}
} else {
label->base.source_position = *pos;
label->statement = statement;
+ label->n_users += 1;
}
eat(':');
{
if (!is_warn_on(WARN_SWITCH_ENUM))
return;
- const type_t *type = skip_typeref(statement->expression->base.type);
+ type_t *type = skip_typeref(statement->expression->base.type);
if (! is_type_enum(type))
return;
- const enum_type_t *enumt = &type->enumt;
+ enum_type_t *enumt = &type->enumt;
/* if we have a default, no warnings */
if (statement->default_label != NULL)
return;
+ determine_enum_values(enumt);
+
/* FIXME: calculation of value should be done while parsing */
/* TODO: quadratic algorithm here. Change to an n log n one */
- long last_value = -1;
- const entity_t *entry = enumt->enume->base.next;
+ const entity_t *entry = enumt->enume->base.next;
for (; entry != NULL && entry->kind == ENTITY_ENUM_VALUE;
entry = entry->base.next) {
- const expression_t *expression = entry->enum_value.value;
- long value = expression != NULL ? fold_constant_to_int(expression) : last_value + 1;
- bool found = false;
- for (const case_label_statement_t *l = statement->first_case; l != NULL; l = l->next) {
+ ir_tarval *value = entry->enum_value.tv;
+ bool found = false;
+ for (const case_label_statement_t *l = statement->first_case; l != NULL;
+ l = l->next) {
if (l->expression == NULL)
continue;
- if (l->first_case <= value && value <= l->last_case) {
+ if (l->first_case == l->last_case && l->first_case != value)
+ continue;
+ if ((tarval_cmp(l->first_case, value) & ir_relation_less_equal)
+ && (tarval_cmp(value, l->last_case) & ir_relation_less_equal)) {
found = true;
break;
}
source_position_t const *const pos = &statement->base.source_position;
warningf(WARN_SWITCH_ENUM, pos, "'%N' not handled in switch", entry);
}
- last_value = value;
}
}
*/
static statement_t *parse_while(void)
{
- statement_t *statement = allocate_statement_zero(STATEMENT_WHILE);
+ statement_t *statement = allocate_statement_zero(STATEMENT_FOR);
eat(T_while);
PUSH_PARENT(statement);
- PUSH_SCOPE_STATEMENT(&statement->whiles.scope);
+ PUSH_SCOPE_STATEMENT(&statement->fors.scope);
expression_t *const cond = parse_condition();
- statement->whiles.condition = cond;
+ statement->fors.condition = cond;
/* ยง6.8.5:2 The controlling expression of an iteration statement shall
* have scalar type. */
semantic_condition(cond, "condition of 'while'-statement");
- statement->whiles.body = parse_loop_body(statement);
+ statement->fors.body = parse_loop_body(statement);
POP_SCOPE();
POP_PARENT();
label_t *const label = get_label("while parsing goto");
if (label) {
+ label->n_users += 1;
label->used = true;
statement->gotos.label = label;
add_anchor_token(T_NUMBER);
add_anchor_token(T_PLUSPLUS);
add_anchor_token(T_STRING_LITERAL);
+ add_anchor_token(T__Alignof);
add_anchor_token(T__Bool);
add_anchor_token(T__Complex);
add_anchor_token(T__Imaginary);
+ add_anchor_token(T__Thread_local);
add_anchor_token(T___PRETTY_FUNCTION__);
- add_anchor_token(T___alignof__);
add_anchor_token(T___attribute__);
add_anchor_token(T___builtin_va_start);
add_anchor_token(T___extension__);
add_anchor_token(T___imag__);
add_anchor_token(T___label__);
add_anchor_token(T___real__);
- add_anchor_token(T___thread);
add_anchor_token(T_asm);
add_anchor_token(T_auto);
add_anchor_token(T_bool);
rem_anchor_token(T_bool);
rem_anchor_token(T_auto);
rem_anchor_token(T_asm);
- rem_anchor_token(T___thread);
rem_anchor_token(T___real__);
rem_anchor_token(T___label__);
rem_anchor_token(T___imag__);
rem_anchor_token(T___extension__);
rem_anchor_token(T___builtin_va_start);
rem_anchor_token(T___attribute__);
- rem_anchor_token(T___alignof__);
rem_anchor_token(T___PRETTY_FUNCTION__);
+ rem_anchor_token(T__Thread_local);
rem_anchor_token(T__Imaginary);
rem_anchor_token(T__Complex);
rem_anchor_token(T__Bool);
+ rem_anchor_token(T__Alignof);
rem_anchor_token(T_STRING_LITERAL);
rem_anchor_token(T_PLUSPLUS);
rem_anchor_token(T_NUMBER);
continue;
why = WARN_UNUSED_FUNCTION;
- s = entity->function.statement != NULL ? "defined" : "declared";
+ s = entity->function.body != NULL ? "defined" : "declared";
} else {
why = WARN_UNUSED_VARIABLE;
s = "defined";
{
environment_stack = NEW_ARR_F(stack_entry_t, 0);
label_stack = NEW_ARR_F(stack_entry_t, 0);
- error_count = 0;
- warning_count = 0;
print_to_file(stderr);
static void prepare_main_collect2(entity_t *const entity)
{
- PUSH_SCOPE(&entity->function.statement->compound.scope);
+ PUSH_SCOPE(&entity->function.body->compound.scope);
// create call to __main
symbol_t *symbol = symbol_table_insert("__main");
expr_statement->base.source_position = builtin_source_position;
expr_statement->expression.expression = call;
- statement_t *statement = entity->function.statement;
- assert(statement->kind == STATEMENT_COMPOUND);
- compound_statement_t *compounds = &statement->compound;
+ statement_t *const body = entity->function.body;
+ assert(body->kind == STATEMENT_COMPOUND);
+ compound_statement_t *compounds = &body->compound;
expr_statement->base.next = compounds->statements;
compounds->statements = expr_statement;