static statement_t *parse_compound_statement(bool inside_expression_statement);
static statement_t *parse_statement(void);
-static expression_t *parse_sub_expression(precedence_t);
+static expression_t *parse_subexpression(precedence_t);
static expression_t *parse_expression(void);
static type_t *parse_typename(void);
static void parse_externals(void);
/**
* 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))) {
static expression_t *parse_constant_expression(void)
{
- expression_t *result = parse_sub_expression(PREC_CONDITIONAL);
+ expression_t *result = parse_subexpression(PREC_CONDITIONAL);
if (!is_constant_expression(result)) {
errorf(&result->base.source_position,
static expression_t *parse_assignment_expression(void)
{
- return parse_sub_expression(PREC_ASSIGNMENT);
+ return parse_subexpression(PREC_ASSIGNMENT);
}
static void warn_string_concat(const source_position_t *pos)
type_t *real_type = skip_typeref(iter->declaration.type);
if (real_type->kind == TYPE_BITFIELD) {
errorf(&designator->source_position,
- "offsetof designator '%Y' may not specify bitfield",
+ "offsetof designator '%Y' must not specify bitfield",
symbol);
goto failed;
}
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);
}
}
}
switch (token.type) {
case T_IDENTIFIER:
if (is_typedef_symbol(token.symbol)) {
+ TYPENAME_START
type = parse_typename();
} else {
+ default:
expression = parse_expression();
type = revert_automatic_type_conversion(expression);
}
break;
-
- TYPENAME_START
- type = parse_typename();
- break;
-
- default:
- expression = parse_expression();
- type = expression->base.type;
- break;
}
in_type_prop = old_type_prop;
in_gcc_extension = old_gcc_extension;
parsed_array_t array;
};
+static construct_type_t *allocate_declarator_zero(construct_type_kind_t const kind, size_t const size)
+{
+ construct_type_t *const cons = obstack_alloc(&temp_obst, size);
+ memset(cons, 0, size);
+ cons->kind = kind;
+ return cons;
+}
+
+/* §6.7.5.1 */
static construct_type_t *parse_pointer_declarator(void)
{
eat('*');
- parsed_pointer_t *pointer = obstack_alloc(&temp_obst, sizeof(pointer[0]));
- memset(pointer, 0, sizeof(pointer[0]));
- pointer->base.kind = CONSTRUCT_POINTER;
- pointer->type_qualifiers = parse_type_qualifiers();
- //pointer->base_variable = base_variable;
+ construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_POINTER, sizeof(parsed_pointer_t));
+ cons->pointer.type_qualifiers = parse_type_qualifiers();
+ //cons->pointer.base_variable = base_variable;
- return (construct_type_t*) pointer;
+ return cons;
}
+/* ISO/IEC 14882:1998(E) §8.3.2 */
static construct_type_t *parse_reference_declarator(void)
{
eat('&');
- construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->reference));
- parsed_reference_t *reference = &cons->reference;
- memset(reference, 0, sizeof(*reference));
- cons->kind = CONSTRUCT_REFERENCE;
+ if (!(c_mode & _CXX))
+ errorf(HERE, "references are only available for C++");
+
+ construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_REFERENCE, sizeof(parsed_reference_t));
return cons;
}
+/* §6.7.5.2 */
static construct_type_t *parse_array_declarator(void)
{
eat('[');
add_anchor_token(']');
- construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->array));
- parsed_array_t *array = &cons->array;
- memset(array, 0, sizeof(*array));
- cons->kind = CONSTRUCT_ARRAY;
+ construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_ARRAY, sizeof(parsed_array_t));
+ parsed_array_t *const array = &cons->array;
- if (next_if(T_static))
- array->is_static = true;
+ bool is_static = next_if(T_static);
type_qualifiers_t type_qualifiers = parse_type_qualifiers();
- if (type_qualifiers != 0 && next_if(T_static))
- array->is_static = true;
+
+ if (!is_static)
+ is_static = next_if(T_static);
+
array->type_qualifiers = type_qualifiers;
+ array->is_static = is_static;
+ expression_t *size = NULL;
if (token.type == '*' && look_ahead(1)->type == ']') {
array->is_variable = true;
next_token();
} else if (token.type != ']') {
- expression_t *const size = parse_assignment_expression();
+ size = parse_assignment_expression();
/* §6.7.5.2:1 Array size must have integer type */
type_t *const orig_type = size->base.type;
mark_vars_read(size, NULL);
}
+ if (is_static && size == NULL)
+ errorf(HERE, "static array parameters require a size");
+
rem_anchor_token(']');
expect(']', end_error);
return cons;
}
+/* §6.7.5.3 */
static construct_type_t *parse_function_declarator(scope_t *scope)
{
type_t *type = allocate_type_zero(TYPE_FUNCTION);
parse_parameters(ftype, scope);
- construct_type_t *cons = obstack_alloc(&temp_obst, sizeof(cons->function));
- construct_function_type_t *function = &cons->function;
- memset(function, 0, sizeof(*function));
- cons->kind = CONSTRUCT_FUNCTION;
- function->function_type = type;
+ construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_FUNCTION, sizeof(construct_function_type_t));
+ cons->function.function_type = type;
return cons;
}
attribute_t *attributes;
} parse_declarator_env_t;
+/* §6.7.5 */
static construct_type_t *parse_inner_declarator(parse_declarator_env_t *env)
{
/* construct a single linked list of construct_type_t's which describe
//variable_t *based = NULL; /* MS __based extension */
switch (token.type) {
case '&':
- if (!(c_mode & _CXX))
- errorf(HERE, "references are only available for C++");
type = parse_reference_declarator();
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);
}
/* TODO: improve error message, user does probably not know what a
* storage class is...
*/
- errorf(HERE, "typename may not have a storage class");
+ errorf(HERE, "typename must not have a storage class");
}
type_t *result = parse_abstract_declarator(specifiers.type);
case T_INTEGER:
kind = EXPR_LITERAL_INTEGER;
check_integer_suffix();
+ type = type_int;
break;
case T_INTEGER_OCTAL:
kind = EXPR_LITERAL_INTEGER_OCTAL;
check_integer_suffix();
+ type = type_int;
break;
case T_INTEGER_HEXADECIMAL:
kind = EXPR_LITERAL_INTEGER_HEXADECIMAL;
check_integer_suffix();
+ type = type_int;
break;
case T_FLOATINGPOINT:
kind = EXPR_LITERAL_FLOATINGPOINT;
expression_t *cast = allocate_expression_zero(EXPR_UNARY_CAST);
cast->base.source_position = source_position;
- expression_t *value = parse_sub_expression(PREC_CAST);
+ expression_t *value = parse_subexpression(PREC_CAST);
cast->base.type = type;
cast->unary.value = value;
goto typeprop_expression;
}
} else {
- expression = parse_sub_expression(PREC_UNARY);
+ expression = parse_subexpression(PREC_UNARY);
typeprop_expression:
tp_expression->typeprop.tp_expression = expression;
}
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);
expect(':', end_error);
end_error:;
expression_t *false_expression =
- parse_sub_expression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL);
+ parse_subexpression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL);
type_t *const orig_true_type = true_expression->base.type;
type_t *const orig_false_type = false_expression->base.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;
bool old_gcc_extension = in_gcc_extension;
in_gcc_extension = true;
- expression_t *expression = parse_sub_expression(PREC_UNARY);
+ expression_t *expression = parse_subexpression(PREC_UNARY);
in_gcc_extension = old_gcc_extension;
return expression;
}
end_error:;
}
- expression_t *const value = parse_sub_expression(PREC_CAST);
+ expression_t *const value = parse_subexpression(PREC_CAST);
result->unary.value = value;
type_t *const type = skip_typeref(value->base.type);
expression_t *unary_expression \
= allocate_expression_zero(unexpression_type); \
eat(token_type); \
- unary_expression->unary.value = parse_sub_expression(PREC_UNARY); \
+ unary_expression->unary.value = parse_subexpression(PREC_UNARY); \
\
sfunc(&unary_expression->unary); \
\
binexpr->binary.left = left; \
eat(token_type); \
\
- expression_t *right = parse_sub_expression(prec_r); \
+ expression_t *right = parse_subexpression(prec_r); \
\
binexpr->binary.right = right; \
sfunc(&binexpr->binary); \
CREATE_BINEXPR_PARSER(',', EXPR_BINARY_COMMA, PREC_ASSIGNMENT, semantic_comma)
-static expression_t *parse_sub_expression(precedence_t precedence)
+static expression_t *parse_subexpression(precedence_t precedence)
{
if (token.type < 0) {
return expected_expression_error();
*/
static expression_t *parse_expression(void)
{
- return parse_sub_expression(PREC_EXPRESSION);
+ return parse_subexpression(PREC_EXPRESSION);
}
/**
"asm output argument is not an lvalue");
}
- if (argument->constraints.begin[0] == '+')
+ if (argument->constraints.begin[0] == '=')
+ determine_lhs_ent(expression, NULL);
+ else
mark_vars_read(expression, NULL);
} else {
mark_vars_read(expression, NULL);
expect('(', end_error);
add_anchor_token(')');
- add_anchor_token(':');
+ if (token.type != T_STRING_LITERAL) {
+ parse_error_expected("after asm(", T_STRING_LITERAL, NULL);
+ goto end_of_asm;
+ }
asm_statement->asm_text = parse_string_literals();
+ add_anchor_token(':');
if (!next_if(':')) {
rem_anchor_token(':');
goto end_of_asm;
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) {
POP_PARENT;
return statement;
-end_error:
- POP_PARENT;
- return create_invalid_statement();
}
/**
eat(':');
if (token.type == '}') {
- /* TODO only warn? */
- if (warning.other && false) {
- warningf(HERE, "label at end of compound statement");
- statement->label.statement = create_empty_statement();
- } else {
- errorf(HERE, "label at end of compound statement");
- statement->label.statement = create_invalid_statement();
- }
+ 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