/**
* Expect the current token is the expected token.
* If not, generate an error, eat the current statement,
- * and goto the end_error label.
+ * and goto the error_label label.
*/
#define expect(expected, error_label) \
do { \
}
}
- ARR_SHRINKLEN(*stack_ptr, (int) new_top);
+ ARR_SHRINKLEN(*stack_ptr, new_top);
}
/**
return ASSIGN_WARNING_POINTER_FROM_INT;
}
} else if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) ||
- (is_type_atomic(type_left, ATOMIC_TYPE_BOOL)
- && is_type_pointer(type_right))) {
+ (is_type_atomic(type_left, ATOMIC_TYPE_BOOL)
+ && is_type_pointer(type_right))) {
return ASSIGN_SUCCESS;
} else if ((is_type_compound(type_left) && is_type_compound(type_right))
|| (is_type_builtin(type_left) && is_type_builtin(type_right))) {
symbol_t *symbol = get_symbol_from_token();
if (symbol == NULL) {
parse_error_expected("while parsing attribute((", T_IDENTIFIER, NULL);
- goto end_error;
+ return NULL;
}
const char *name = symbol->string;
attribute->a.arguments = parse_attribute_arguments();
return attribute;
-
-end_error:
- return NULL;
}
static attribute_t *parse_attribute_gnu(void)
long array_size = type->array.size;
if (index >= array_size) {
errorf(&designator->source_position,
- "designator [%E] (%d) exceeds array size %d",
- array_index, index, array_size);
+ "designator [%E] (%d) exceeds array size %d",
+ array_index, index, array_size);
}
}
}
break;
char const* wrong;
- case STORAGE_CLASS_AUTO: wrong = "auto"; goto wrong_thread_stoarge_class;
- case STORAGE_CLASS_REGISTER: wrong = "register"; goto wrong_thread_stoarge_class;
- case STORAGE_CLASS_TYPEDEF: wrong = "typedef"; goto wrong_thread_stoarge_class;
-wrong_thread_stoarge_class:
+ case STORAGE_CLASS_AUTO: wrong = "auto"; goto wrong_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);
break;
}
bool in_function_scope = current_function != NULL;
if (specifiers->thread_local || (
- specifiers->storage_class != STORAGE_CLASS_EXTERN &&
- specifiers->storage_class != STORAGE_CLASS_NONE &&
- (in_function_scope || specifiers->storage_class != STORAGE_CLASS_STATIC)
- )) {
+ specifiers->storage_class != STORAGE_CLASS_EXTERN &&
+ specifiers->storage_class != STORAGE_CLASS_NONE &&
+ (in_function_scope || specifiers->storage_class != STORAGE_CLASS_STATIC)
+ )) {
errorf(&env.source_position,
"invalid storage class for function '%Y'", env.symbol);
}
}
break;
}
- case bk_gnu_builtin_prefetch: {
+ 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)) {
+ errorf(&call->base.source_position,
+ "second argument of '%Y' must be a constant expression",
+ call->function->reference.entity->base.symbol);
+ }
+ break;
+ case bk_gnu_builtin_prefetch:
/* second and third argument must be constant if existent */
+ if (call->arguments == NULL)
+ break;
call_argument_t *rw = call->arguments->next;
call_argument_t *locality = NULL;
locality = rw->next;
}
break;
- }
default:
break;
}
/* do default promotion for other arguments */
for (; argument != NULL; argument = argument->next) {
type_t *type = argument->expression->base.type;
+ if (!is_type_object(skip_typeref(type))) {
+ errorf(&argument->expression->base.source_position,
+ "call argument '%E' must not be void", argument->expression);
+ }
type = get_default_promoted_type(type);
} else if (is_type_arithmetic(true_type)
&& is_type_arithmetic(false_type)) {
result_type = semantic_arithmetic(true_type, false_type);
-
- true_expression = create_implicit_cast(true_expression, result_type);
- false_expression = create_implicit_cast(false_expression, result_type);
-
- conditional->true_expression = true_expression;
- conditional->false_expression = false_expression;
- conditional->base.type = result_type;
} else if (same_compound_type(true_type, false_type)) {
/* just take 1 of the 2 types */
result_type = true_type;
result_type = pointer_type;
} else {
if (is_type_valid(other_type)) {
- type_error_incompatible("while parsing conditional",
+ type_error_incompatible("while parsing conditional",
&expression->base.source_position, true_type, false_type);
}
result_type = type_error_type;
return create_invalid_statement();
}
+static statement_t *parse_label_inner_statement(char const *const label, bool const eat_empty_stmt)
+{
+ statement_t *inner_stmt;
+ switch (token.type) {
+ case '}':
+ errorf(HERE, "%s at end of compound statement", label);
+ inner_stmt = create_invalid_statement();
+ break;
+
+ case ';':
+ if (eat_empty_stmt) {
+ /* Eat an empty statement here, to avoid the warning about an empty
+ * statement after a label. label:; is commonly used to have a label
+ * before a closing brace. */
+ inner_stmt = create_empty_statement();
+ next_token();
+ break;
+ }
+ /* FALLTHROUGH */
+
+ default:
+ inner_stmt = parse_statement();
+ if (inner_stmt->kind == STATEMENT_DECLARATION) {
+ errorf(&inner_stmt->base.source_position, "declaration after %s", label);
+ }
+ break;
+ }
+ return inner_stmt;
+}
+
/**
* Parse a case statement.
*/
errorf(pos, "case label not within a switch statement");
}
- statement_t *const inner_stmt = parse_statement();
- statement->case_label.statement = inner_stmt;
- if (inner_stmt->kind == STATEMENT_DECLARATION) {
- errorf(&inner_stmt->base.source_position, "declaration after case label");
- }
+ statement->case_label.statement = parse_label_inner_statement("case label", false);
POP_PARENT;
return statement;
PUSH_PARENT(statement);
expect(':', end_error);
+end_error:
+
if (current_switch != NULL) {
const case_label_statement_t *def_label = current_switch->default_label;
if (def_label != NULL) {
"'default' label not within a switch statement");
}
- statement_t *const inner_stmt = parse_statement();
- statement->case_label.statement = inner_stmt;
- if (inner_stmt->kind == STATEMENT_DECLARATION) {
- errorf(&inner_stmt->base.source_position, "declaration after default label");
- }
+ statement->case_label.statement = parse_label_inner_statement("default label", false);
POP_PARENT;
return statement;
-end_error:
- POP_PARENT;
- return create_invalid_statement();
}
/**
eat(':');
- if (token.type == '}') {
- errorf(HERE, "label at end of compound statement");
- statement->label.statement = create_invalid_statement();
- } else if (token.type == ';') {
- /* Eat an empty statement here, to avoid the warning about an empty
- * statement after a label. label:; is commonly used to have a label
- * before a closing brace. */
- statement->label.statement = create_empty_statement();
- next_token();
- } else {
- statement_t *const inner_stmt = parse_statement();
- statement->label.statement = inner_stmt;
- if (inner_stmt->kind == STATEMENT_DECLARATION) {
- errorf(&inner_stmt->base.source_position, "declaration after label");
- }
- }
+ statement->label.statement = parse_label_inner_statement("label", true);
/* remember the labels in a list for later checking */
*label_anchor = &statement->label;
else
parse_error_expected("while parsing goto", T_IDENTIFIER, NULL);
eat_until_anchor();
- goto end_error;
+ return create_invalid_statement();
}
/* remember the goto's in a list for later checking */
expect(';', end_error);
- return statement;
end_error:
- return create_invalid_statement();
+ return statement;
}
/**
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);
}
next_token();
} while (next_if(','));
- eat(';');
+ expect(';', end_error);
end_error:
statement->declaration.declarations_begin = begin;
statement->declaration.declarations_end = end;
switch (la1_type) {
case '&':
case '*':
- if (get_entity(token.symbol, NAMESPACE_NORMAL) != NULL)
- goto expression_statment;
- /* FALLTHROUGH */
-
+ if (get_entity(token.symbol, NAMESPACE_NORMAL) != NULL) {
+ default:
+ statement = parse_expression_statement();
+ } else {
DECLARATION_START
case T_IDENTIFIER:
- statement = parse_declaration_statement();
- break;
-
- default:
-expression_statment:
- statement = parse_expression_statement();
+ statement = parse_declaration_statement();
+ }
break;
}
}