return res;
}
+/**
+ * Returns the size of an entity node.
+ *
+ * @param kind the entity kind
+ */
static size_t get_entity_struct_size(entity_kind_t kind)
{
static const size_t sizes[] = {
return sizes[kind];
}
+/**
+ * Allocate an entity of given kind and initialize all
+ * fields with zero.
+ */
static entity_t *allocate_entity_zero(entity_kind_t kind)
{
size_t size = get_entity_struct_size(kind);
/**
* Allocate a statement node of given kind and initialize all
- * fields with zero.
+ * fields with zero. Sets its source position to the position
+ * of the current token.
*/
static statement_t *allocate_statement_zero(statement_kind_t kind)
{
}
/**
- * Creates a new invalid expression.
+ * Creates a new invalid expression at the source position
+ * of the current token.
*/
static expression_t *create_invalid_expression(void)
{
}
/**
- * Adds a token to the token anchor set (a multi-set).
+ * Adds a token type to the token type anchor set (a multi-set).
*/
static void add_anchor_token(int token_type)
{
++token_anchor_set[token_type];
}
+/**
+ * Set the number of tokens types of the given type
+ * to zero and return the old count.
+ */
static int save_and_reset_anchor_state(int token_type)
{
assert(0 <= token_type && token_type < T_LAST_TOKEN);
return count;
}
+/**
+ * Restore the number of token types to the given count.
+ */
static void restore_anchor_state(int token_type, int count)
{
assert(0 <= token_type && token_type < T_LAST_TOKEN);
}
/**
- * Remove a token from the token anchor set (a multi-set).
+ * Remove a token type from the token type anchor set (a multi-set).
*/
static void rem_anchor_token(int token_type)
{
--token_anchor_set[token_type];
}
+/**
+ * Return true if the token type of the current token is
+ * in the anchor set.
+ */
static bool at_anchor(void)
{
if (token.type < 0)
}
/**
- * Eat tokens until a matching token is found.
+ * Eat tokens until a matching token type is found.
*/
static void eat_until_matching_token(int type)
{
}
}
+/**
+ * Eat a whole block from input tokens.
+ */
static void eat_block(void)
{
eat_until_matching_token('{');
}
va_list ap;
va_start(ap, message);
- errorf(HERE, "got '%K', expected %#k", &token, &ap, ", ");
+ errorf(HERE, "got %K, expected %#k", &token, &ap, ", ");
va_end(ap);
}
}
/**
- * Expect the the current token is the expected token.
+ * Expect the current token is the expected token.
* If not, generate an error, eat the current statement,
* and goto the end_error label.
*/
-#define expect(expected) \
+#define expect(expected, error_label) \
do { \
if (UNLIKELY(token.type != (expected))) { \
parse_error_expected(NULL, (expected), NULL); \
if (token.type == expected) \
next_token(); \
rem_anchor_token(expected); \
- goto end_error; \
+ goto error_label; \
} \
next_token(); \
} while (0)
+/**
+ * Push a given scope on the scope stack and make it the
+ * current scope
+ */
static scope_t *scope_push(scope_t *new_scope)
{
if (current_scope != NULL) {
return old_scope;
}
+/**
+ * Pop the current scope from the scope stack.
+ */
static void scope_pop(scope_t *old_scope)
{
current_scope = old_scope;
return (int) akind;
}
+/**
+ * Return the type rank for an atomic type.
+ */
static int get_rank(const type_t *type)
{
assert(!is_typeref(type));
return get_akind_rank(type->atomic.akind);
}
+/**
+ * Do integer promotion for a given type.
+ *
+ * @param type the type to promote
+ * @return the promoted type
+ */
static type_t *promote_integer(type_t *type)
{
if (type->kind == TYPE_BITFIELD)
}
/**
- * Check if a given expression represents the 0 pointer constant.
+ * Check if a given expression represents a null pointer constant.
+ *
+ * @param expression the expression to check
*/
static bool is_null_pointer_constant(const expression_t *expression)
{
}
/**
- * Allocate a new gnu temporal attribute.
+ * Allocate a new gnu temporal attribute of given kind.
*/
static gnu_attribute_t *allocate_gnu_attribute(gnu_attribute_kind_t kind)
{
}
/**
- * parse one constant expression argument.
+ * Parse one constant expression argument of the given attribute.
*/
static void parse_gnu_attribute_const_arg(gnu_attribute_t *attribute)
{
add_anchor_token(')');
expression = parse_constant_expression();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
attribute->u.argument = fold_constant(expression);
return;
end_error:
}
/**
- * parse a list of constant expressions arguments.
+ * Parse a list of constant expressions arguments of the given attribute.
*/
static void parse_gnu_attribute_const_arg_list(gnu_attribute_t *attribute)
{
}
rem_anchor_token(',');
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
return;
end_error:
attribute->invalid = true;
}
/**
- * parse one string literal argument.
+ * Parse one string literal argument of the given attribute.
*/
static void parse_gnu_attribute_string_arg(gnu_attribute_t *attribute,
string_t *string)
}
*string = parse_string_literals();
rem_anchor_token('(');
- expect(')');
+ expect(')', end_error);
return;
end_error:
attribute->invalid = true;
}
/**
- * parse one tls model.
+ * Parse one tls model of the given attribute.
*/
static void parse_gnu_attribute_tls_model_arg(gnu_attribute_t *attribute)
{
}
/**
- * parse one tls model.
+ * Parse one tls model of the given attribute.
*/
static void parse_gnu_attribute_visibility_arg(gnu_attribute_t *attribute)
{
}
/**
- * parse one (code) model.
+ * Parse one (code) model of the given attribute.
*/
static void parse_gnu_attribute_model_arg(gnu_attribute_t *attribute)
{
attribute->invalid = true;
}
+/**
+ * Parse one mode of the given attribute.
+ */
static void parse_gnu_attribute_mode_arg(gnu_attribute_t *attribute)
{
/* TODO: find out what is allowed here... */
add_anchor_token(')');
if (token.type != T_IDENTIFIER) {
- expect(T_IDENTIFIER);
+ expect(T_IDENTIFIER, end_error);
}
/* This isn't really correct, the backend should provide a list of machine
next_token();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
return;
end_error:
attribute->invalid = true;
}
/**
- * parse one interrupt argument.
+ * Parse one interrupt argument of the given attribute.
*/
static void parse_gnu_attribute_interrupt_arg(gnu_attribute_t *attribute)
{
}
/**
- * parse ( identifier, const expression, const expression )
+ * Parse ( identifier, const expression, const expression )
*/
static void parse_gnu_attribute_format_args(gnu_attribute_t *attribute)
{
}
next_token();
- expect(',');
+ expect(',', end_error);
add_anchor_token(')');
add_anchor_token(',');
parse_constant_expression();
rem_anchor_token(',');
rem_anchor_token(')');
- expect(',');
+ expect(',', end_error);
add_anchor_token(')');
parse_constant_expression();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
return;
end_error:
attribute->u.value = true;
}
+/**
+ * Check that a given GNU attribute has no arguments.
+ */
static void check_no_argument(gnu_attribute_t *attribute, const char *name)
{
if (!attribute->have_arguments)
gnu_attribute_t *attribute;
eat(T___attribute__);
- expect('(');
- expect('(');
+ expect('(', end_error);
+ expect('(', end_error);
if (token.type != ')') {
/* find the end of the list */
next_token();
}
}
- expect(')');
- expect(')');
+ expect(')', end_error);
+ expect(')', end_error);
end_error:
*attributes = head;
case T_asm:
next_token();
- expect('(');
+ expect('(', end_error);
if (token.type != T_STRING_LITERAL) {
parse_error_expected("while parsing assembler attribute",
T_STRING_LITERAL, NULL);
} else {
parse_string_literals();
}
- expect(')');
+ expect(')', end_error);
continue;
case T_cdecl: modifiers |= DM_CDECL; break;
case T___thiscall:
/* TODO record modifier */
if (warning.other)
- warningf(HERE, "Ignoring declaration modifier '%K'", &token);
+ warningf(HERE, "Ignoring declaration modifier %K", &token);
break;
end_error:
add_anchor_token(']');
designator->array_index = parse_constant_expression();
rem_anchor_token(']');
- expect(']');
+ expect(']', end_error);
break;
case '.':
designator = allocate_ast_zero(sizeof(designator[0]));
next_token();
break;
default:
- expect('=');
+ expect('=', end_error);
return result;
}
if (type != NULL) {
ascend_from_subtype(path);
- expect('}');
+ expect('}', end_error);
} else {
- expect('}');
+ expect('}', end_error);
goto error_parse_next;
}
}
if (token.type == '}') {
break;
}
- expect(',');
+ expect(',', end_error);
if (token.type == '}') {
break;
}
max_index = path.max_index;
DEL_ARR_F(path.path);
- expect('}');
+ expect('}', end_error);
} else {
/* parse_scalar_initializer() also works in this case: we simply
* have an expression without {} around it */
} while (token.type != '}');
rem_anchor_token('}');
- expect('}');
+ expect('}', end_error);
end_error:
;
if (token.type == '{') {
if (entity->enume.complete) {
- errorf(HERE, "multiple definitions of enum %Y (previous definition %P)",
+ errorf(HERE, "multiple definitions of 'enum %Y' (previous definition %P)",
symbol, &entity->base.source_position);
}
if (symbol != NULL) {
anonymous_entity = entity;
}
} else if (!entity->enume.complete && !(c_mode & _GNUC)) {
- errorf(HERE, "enum %Y used before definition (incomplete enumes are a GNU extension)",
+ errorf(HERE, "'enum %Y' used before definition (incomplete enums are a GNU extension)",
symbol);
}
type_t *type;
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression_t *expression = NULL;
in_gcc_extension = old_gcc_extension;
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
type_t *typeof_type = allocate_type_zero(TYPE_TYPEOF);
typeof_type->typeoft.expression = expression;
symbol_t *symbol = token.v.symbol;
if (symbol == sym_align) {
next_token();
- expect('(');
+ expect('(', end_error);
if (token.type != T_INTEGER)
goto end_error;
if (check_alignment_value(token.v.intvalue)) {
specifiers->alignment = (unsigned char)token.v.intvalue;
}
next_token();
- expect(')');
+ expect(')', end_error);
} else if (symbol == sym_allocate) {
next_token();
- expect('(');
+ expect('(', end_error);
if (token.type != T_IDENTIFIER)
goto end_error;
(void)token.v.symbol;
- expect(')');
+ expect(')', end_error);
} else if (symbol == sym_dllimport) {
next_token();
DET_MOD(dllimport, DM_DLLIMPORT);
DET_MOD(novtable, DM_NOVTABLE);
} else if (symbol == sym_property) {
next_token();
- expect('(');
+ expect('(', end_error);
for (;;) {
bool is_get = false;
if (token.type != T_IDENTIFIER)
goto end_error;
}
next_token();
- expect('=');
+ expect('=', end_error);
if (token.type != T_IDENTIFIER)
goto end_error;
if (is_get) {
}
break;
}
- expect(')');
+ expect(')', end_error);
} else if (symbol == sym_selectany) {
next_token();
DET_MOD(selectany, DM_SELECTANY);
} else if (symbol == sym_uuid) {
next_token();
- expect('(');
+ expect('(', end_error);
if (token.type != T_STRING_LITERAL)
goto end_error;
next_token();
- expect(')');
+ expect(')', end_error);
} else if (symbol == sym_deprecated) {
next_token();
if (specifiers->deprecated != 0 && warning.other)
} else {
errorf(HERE, "string literal expected");
}
- expect(')');
+ expect(')', end_error);
}
} else if (symbol == sym_noalias) {
next_token();
DET_MOD(noalias, DM_NOALIAS);
} else {
if (warning.other)
- warningf(HERE, "Unknown modifier %Y ignored", token.v.symbol);
+ warningf(HERE, "Unknown modifier '%Y' ignored", token.v.symbol);
next_token();
if (token.type == '(')
skip_until(')');
entity->declaration.type = type_error_type;
entity->declaration.implicit = true;
} else if (kind == ENTITY_TYPEDEF) {
- entity->typedefe.type = type_error_type;
+ entity->typedefe.type = type_error_type;
+ entity->typedefe.builtin = true;
}
record_entity(entity, false);
return entity;
if (offset > size)
need_pad = true;
- if (warning.padded && need_pad) {
- warningf(&compound->base.source_position,
- "'%#T' needs padding", type, compound->base.symbol);
- }
- if (warning.packed && !need_pad) {
- warningf(&compound->base.source_position,
- "superfluous packed attribute on '%#T'",
- type, compound->base.symbol);
+ if (need_pad) {
+ if (warning.padded) {
+ warningf(&compound->base.source_position, "'%T' needs padding", type);
+ }
+ } else {
+ if (compound->modifiers & DM_PACKED && warning.packed) {
+ warningf(&compound->base.source_position,
+ "superfluous packed attribute on '%T'", type);
+ }
}
type->base.size = offset;
case T__declspec:
next_token();
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
parse_microsoft_extended_decl_modifier(specifiers);
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
break;
case T___thread:
case T_IDENTIFIER:
case '&':
case '*':
- errorf(HERE, "discarding stray '%K' in declaration specifier", &token);
+ errorf(HERE, "discarding stray %K in declaration specifier", &token);
next_token();
continue;
case T_IDENTIFIER:
case '&':
case '*': {
- errorf(HERE, "'%K' does not name a type", &token);
+ errorf(HERE, "%K does not name a type", &token);
entity_t *entity =
create_error_entity(token.v.symbol, ENTITY_TYPEDEF);
type_t *type = skip_typeref(entity->declaration.type);
if (is_type_incomplete(type)) {
errorf(&entity->base.source_position,
- "parameter '%Y' has incomplete type %T", entity->base.symbol,
+ "parameter '%Y' has incomplete type '%T'", entity->base.symbol,
entity->declaration.type);
}
}
parameters_finished:
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
end_error:
restore_anchor_state(',', saved_comma_state);
}
rem_anchor_token(']');
- expect(']');
+ expect(']', end_error);
end_error:
return &array->construct_type;
case T__based:
next_token();
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
parse_microsoft_based(&base_spec);
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
continue;
default:
next_token();
break;
case '(':
- next_token();
- add_anchor_token(')');
- inner_types = parse_inner_declarator(env, may_be_abstract);
- if (inner_types != NULL) {
- /* All later declarators only modify the return type */
- env = NULL;
+ /* §6.7.6:2 footnote 126: Empty parentheses in a type name are
+ * interpreted as ``function with no parameter specification'', rather
+ * than redundant parentheses around the omitted identifier. */
+ if (look_ahead(1)->type != ')') {
+ next_token();
+ add_anchor_token(')');
+ inner_types = parse_inner_declarator(env, may_be_abstract);
+ if (inner_types != NULL) {
+ /* All later declarators only modify the return type */
+ env = NULL;
+ }
+ rem_anchor_token(')');
+ expect(')', end_error);
}
- rem_anchor_token(')');
- expect(')');
break;
default:
if (may_be_abstract)
env.symbol);
}
} else if (flags & DECL_IS_PARAMETER) {
- orig_type = semantic_parameter(&env.source_position, type,
+ orig_type = semantic_parameter(&env.source_position, orig_type,
specifiers, env.symbol);
entity = allocate_entity_zero(ENTITY_PARAMETER);
static void parser_error_multiple_definition(entity_t *entity,
const source_position_t *source_position)
{
- errorf(source_position, "multiple definition of symbol '%Y' (declared %P)",
+ errorf(source_position, "multiple definition of '%Y' (declared %P)",
entity->base.symbol, &entity->base.source_position);
}
ndeclaration = parse_declarator(specifiers, flags);
rem_anchor_token('=');
}
- expect(';');
+ expect(';', end_error);
end_error:
anonymous_entity = NULL;
}
if (is_definition) {
- errorf(HERE, "parameter %Y is initialised", entity->base.symbol);
+ errorf(HERE, "parameter '%Y' is initialised", entity->base.symbol);
}
return record_entity(entity, false);
declaration_statement_t const *const decl = &stmt->declaration;
entity_t const * ent = decl->declarations_begin;
entity_t const *const last = decl->declarations_end;
- for (;; ent = ent->base.next) {
- if (ent->kind == ENTITY_VARIABLE &&
- ent->variable.initializer != NULL &&
- !initializer_returns(ent->variable.initializer)) {
- return;
+ if (ent != NULL) {
+ for (;; ent = ent->base.next) {
+ if (ent->kind == ENTITY_VARIABLE &&
+ ent->variable.initializer != NULL &&
+ !initializer_returns(ent->variable.initializer)) {
+ return;
+ }
+ if (ent == last)
+ break;
}
- if (ent == last)
- break;
}
next = stmt->base.next;
break;
break;
next_token();
}
- expect(';');
+ expect(';', end_error);
end_error:
anonymous_entity = NULL;
{
/* skip the error message if the error token was read */
if (token.type != T_ERROR) {
- errorf(HERE, "expected expression, got token '%K'", &token);
+ errorf(HERE, "expected expression, got token %K", &token);
}
next_token();
case T___builtin_expect:
return make_function_2_type(type_long, type_long, type_long);
default:
- internal_errorf(HERE, "not implemented builtin symbol found");
+ internal_errorf(HERE, "not implemented builtin identifier found");
}
}
if (entity == NULL) {
if (!strict_mode && look_ahead(1)->type == '(') {
/* an implicitly declared function */
- if (warning.implicit_function_declaration) {
- warningf(HERE, "implicit declaration of function '%Y'",
- symbol);
+ if (warning.error_implicit_function_declaration) {
+ errorf(HERE, "implicit declaration of function '%Y'", symbol);
+ } else if (warning.implicit_function_declaration) {
+ warningf(HERE, "implicit declaration of function '%Y'", symbol);
}
entity = create_implicit_function(symbol, HERE);
} else {
- errorf(HERE, "unknown symbol '%Y' found.", symbol);
+ errorf(HERE, "unknown identifier '%Y' found.", symbol);
entity = create_error_entity(symbol, ENTITY_VARIABLE);
}
}
type_t *type = parse_typename();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
if (token.type == '{') {
return parse_compound_literal(type);
expression->base.type = type;
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
end_error:
return expression;
add_anchor_token(')');
expression_t *result = parse_expression();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
end_error:
return result;
designator->source_position = *HERE;
designator->array_index = parse_expression();
rem_anchor_token(']');
- expect(']');
+ expect(']', end_error);
if (designator->array_index == NULL) {
return NULL;
}
eat(T___builtin_offsetof);
- expect('(');
+ expect('(', end_error);
add_anchor_token(',');
type_t *type = parse_typename();
rem_anchor_token(',');
- expect(',');
+ expect(',', end_error);
add_anchor_token(')');
designator_t *designator = parse_designator();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
expression->offsetofe.type = type;
expression->offsetofe.designator = designator;
eat(T___builtin_va_start);
- expect('(');
+ expect('(', end_error);
add_anchor_token(',');
expression->va_starte.ap = parse_assignment_expression();
rem_anchor_token(',');
- expect(',');
+ expect(',', end_error);
expression_t *const expr = parse_assignment_expression();
if (expr->kind == EXPR_REFERENCE) {
entity_t *const entity = expr->reference.entity;
} else {
expression->va_starte.parameter = &entity->variable;
}
- expect(')');
+ expect(')', end_error);
return expression;
}
- expect(')');
+ expect(')', end_error);
end_error:
return create_invalid_expression();
}
eat(T___builtin_va_arg);
- expect('(');
+ expect('(', end_error);
expression->va_arge.ap = parse_assignment_expression();
- expect(',');
+ expect(',', end_error);
expression->base.type = parse_typename();
- expect(')');
+ expect(')', end_error);
return expression;
end_error:
eat(T___builtin_constant_p);
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression->builtin_constant.value = parse_assignment_expression();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
expression->base.type = type_int;
return expression;
eat(T___builtin_prefetch);
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression->builtin_prefetch.adr = parse_assignment_expression();
if (token.type == ',') {
expression->builtin_prefetch.locality = parse_assignment_expression();
}
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
expression->base.type = type_void;
return expression;
expression->base.source_position = *HERE;
next_token();
- expect('(');
+ expect('(', end_error);
expression->binary.left = parse_assignment_expression();
- expect(',');
+ expect(',', end_error);
expression->binary.right = parse_assignment_expression();
- expect(')');
+ expect(')', end_error);
type_t *const orig_type_left = expression->binary.left->base.type;
type_t *const orig_type_right = expression->binary.right->base.type;
#if 0
/**
- * Parses a __builtin_expect() expression.
+ * Parses a __builtin_expect(, end_error) expression.
*/
-static expression_t *parse_builtin_expect(void)
+static expression_t *parse_builtin_expect(void, end_error)
{
expression_t *expression
= allocate_expression_zero(EXPR_BINARY_BUILTIN_EXPECT);
eat(T___builtin_expect);
- expect('(');
+ expect('(', end_error);
expression->binary.left = parse_assignment_expression();
- expect(',');
+ expect(',', end_error);
expression->binary.right = parse_constant_expression();
- expect(')');
+ expect(')', end_error);
expression->base.type = expression->binary.left->base.type;
eat(T__assume);
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression->unary.value = parse_assignment_expression();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
expression->base.type = type_void;
return expression;
}
rem_anchor_token(',');
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
end_error:
return cnst;
case T___noop: return parse_noop_expression();
}
- errorf(HERE, "unexpected token '%K', expected an expression", &token);
+ errorf(HERE, "unexpected token %K, expected an expression", &token);
return create_invalid_expression();
}
expression->base.type = automatic_type_conversion(return_type);
rem_anchor_token(']');
- expect(']');
+ expect(']', end_error);
end_error:
return expression;
}
add_anchor_token(')');
orig_type = parse_typename();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
if (token.type == '{') {
/* It was not sizeof(type) after all. It is sizeof of an expression
symbol, type_left);
}
create_error_entry:
- return create_invalid_expression();
+ entry = create_error_entity(symbol, ENTITY_COMPOUND_MEMBER);
}
assert(is_declaration(entry));
}
rem_anchor_token(',');
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
if (function_type == NULL)
return result;
true_expression = parse_expression();
}
rem_anchor_token(':');
- expect(':');
+ expect(':', end_error);
expression_t *false_expression =
parse_sub_expression(c_mode & _CXX ? PREC_ASSIGNMENT : PREC_CONDITIONAL);
eat(T___builtin_classify_type);
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression_t *expression = parse_expression();
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
result->classify_type.type_expression = expression;
return result;
if (token.type == '[') {
next_token();
result->kind = EXPR_UNARY_DELETE_ARRAY;
- expect(']');
+ expect(']', end_error);
end_error:;
}
}
argument->symbol = token.v.symbol;
- expect(']');
+ expect(']', end_error);
}
argument->constraints = parse_string_literals();
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression_t *expression = parse_expression();
rem_anchor_token(')');
mark_vars_read(expression, NULL);
}
argument->expression = expression;
- expect(')');
+ expect(')', end_error);
set_address_taken(expression, true);
asm_statement->is_volatile = true;
}
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
add_anchor_token(':');
asm_statement->asm_text = parse_string_literals();
end_of_asm:
rem_anchor_token(')');
- expect(')');
- expect(';');
+ expect(')', end_error);
+ expect(';', end_error);
if (asm_statement->outputs == NULL) {
/* GCC: An 'asm' instruction without any output operands will be treated
PUSH_PARENT(statement);
- expect(':');
+ expect(':', end_error);
end_error:
if (current_switch != NULL) {
PUSH_PARENT(statement);
- expect(':');
+ expect(':', end_error);
if (current_switch != NULL) {
const case_label_statement_t *def_label = current_switch->default_label;
if (def_label != NULL) {
add_anchor_token('{');
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression_t *const expr = parse_expression();
statement->ifs.condition = expr;
semantic_condition(expr, "condition of 'if'-statment");
mark_vars_read(expr, NULL);
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
end_error:
rem_anchor_token('{');
PUSH_PARENT(statement);
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression_t *const expr = parse_expression();
mark_vars_read(expr, NULL);
type = type_error_type;
}
statement->switchs.expression = create_implicit_cast(expr, type);
- expect(')');
+ expect(')', end_error);
rem_anchor_token(')');
switch_statement_t *rem = current_switch;
PUSH_PARENT(statement);
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression_t *const cond = parse_expression();
statement->whiles.condition = cond;
semantic_condition(cond, "condition of 'while'-statement");
mark_vars_read(cond, NULL);
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
statement->whiles.body = parse_loop_body(statement);
statement->do_while.body = parse_loop_body(statement);
rem_anchor_token(T_while);
- expect(T_while);
- expect('(');
+ expect(T_while, end_error);
+ expect('(', end_error);
add_anchor_token(')');
expression_t *const cond = parse_expression();
statement->do_while.condition = cond;
semantic_condition(cond, "condition of 'do-while'-statement");
mark_vars_read(cond, NULL);
rem_anchor_token(')');
- expect(')');
- expect(';');
+ expect(')', end_error);
+ expect(';', end_error);
POP_PARENT;
return statement;
eat(T_for);
+ expect('(', end_error1);
+ add_anchor_token(')');
+
PUSH_PARENT(statement);
size_t const top = environment_top();
scope_t *old_scope = scope_push(&statement->fors.scope);
- expect('(');
- add_anchor_token(')');
-
if (token.type == ';') {
next_token();
} else if (is_declaration_specifier(&token, false)) {
"initialisation of 'for'-statement has no effect");
}
rem_anchor_token(';');
- expect(';');
+ expect(';', end_error2);
}
if (token.type != ';') {
mark_vars_read(cond, NULL);
rem_anchor_token(';');
}
- expect(';');
+ expect(';', end_error2);
if (token.type != ')') {
expression_t *const step = parse_expression();
statement->fors.step = step;
"step of 'for'-statement has no effect");
}
}
- expect(')');
+ expect(')', end_error2);
rem_anchor_token(')');
statement->fors.body = parse_loop_body(statement);
POP_PARENT;
return statement;
-end_error:
+end_error2:
POP_PARENT;
rem_anchor_token(')');
assert(current_scope == &statement->fors.scope);
scope_pop(old_scope);
environment_pop_to(top);
+ /* fallthrough */
+end_error1:
return create_invalid_statement();
}
*goto_anchor = &statement->gotos;
goto_anchor = &statement->gotos.next;
- expect(';');
+ expect(';', end_error);
return statement;
end_error:
statement_t *statement = allocate_statement_zero(STATEMENT_CONTINUE);
eat(T_continue);
- expect(';');
+ expect(';', end_error);
end_error:
return statement;
statement_t *statement = allocate_statement_zero(STATEMENT_BREAK);
eat(T_break);
- expect(';');
+ expect(';', end_error);
end_error:
return statement;
statement_t *statement = allocate_statement_zero(STATEMENT_LEAVE);
eat(T___leave);
- expect(';');
+ expect(';', end_error);
end_error:
return statement;
}
statement->returns.value = return_value;
- expect(';');
+ expect(';', end_error);
end_error:
return statement;
statement->expression.expression = expr;
mark_vars_read(expr, ENT_ANY);
- expect(';');
+ expect(';', end_error);
end_error:
return statement;
if (token.type == T___except) {
eat(T___except);
- expect('(');
+ expect('(', end_error);
add_anchor_token(')');
expression_t *const expr = parse_expression();
mark_vars_read(expr, NULL);
}
statement->ms_try.except_expression = create_implicit_cast(expr, type);
rem_anchor_token(')');
- expect(')');
+ expect(')', end_error);
statement->ms_try.final_statement = parse_compound_statement(false);
} else if (token.type == T__finally) {
eat(T___finally);
size_t const top = environment_top();
scope_t *old_scope = scope_push(&entity->namespacee.members);
- expect('{');
+ expect('{', end_error);
parse_externals();
- expect('}');
+ expect('}', end_error);
end_error:
assert(current_scope == &entity->namespacee.members);
break;
default:
- errorf(HERE, "unexpected token '%K' while parsing statement", &token);
+ errorf(HERE, "unexpected token %K while parsing statement", &token);
statement = create_invalid_statement();
if (!at_anchor())
next_token();
eat('{');
add_anchor_token('}');
+ /* tokens, which can start a statement */
+ /* TODO MS, __builtin_FOO */
+ add_anchor_token('!');
+ add_anchor_token('&');
+ add_anchor_token('(');
+ add_anchor_token('*');
+ add_anchor_token('+');
+ add_anchor_token('-');
+ add_anchor_token('{');
+ add_anchor_token('~');
+ add_anchor_token(T_CHARACTER_CONSTANT);
+ add_anchor_token(T_COLONCOLON);
+ add_anchor_token(T_FLOATINGPOINT);
+ add_anchor_token(T_IDENTIFIER);
+ add_anchor_token(T_INTEGER);
+ add_anchor_token(T_MINUSMINUS);
+ add_anchor_token(T_PLUSPLUS);
+ add_anchor_token(T_STRING_LITERAL);
+ add_anchor_token(T_WIDE_CHARACTER_CONSTANT);
+ add_anchor_token(T_WIDE_STRING_LITERAL);
+ add_anchor_token(T__Bool);
+ add_anchor_token(T__Complex);
+ add_anchor_token(T__Imaginary);
+ add_anchor_token(T___FUNCTION__);
+ 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___func__);
+ 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);
+ add_anchor_token(T_break);
+ add_anchor_token(T_case);
+ add_anchor_token(T_char);
+ add_anchor_token(T_class);
+ add_anchor_token(T_const);
+ add_anchor_token(T_const_cast);
+ add_anchor_token(T_continue);
+ add_anchor_token(T_default);
+ add_anchor_token(T_delete);
+ add_anchor_token(T_double);
+ add_anchor_token(T_do);
+ add_anchor_token(T_dynamic_cast);
+ add_anchor_token(T_enum);
+ add_anchor_token(T_extern);
+ add_anchor_token(T_false);
+ add_anchor_token(T_float);
+ add_anchor_token(T_for);
+ add_anchor_token(T_goto);
+ add_anchor_token(T_if);
+ add_anchor_token(T_inline);
+ add_anchor_token(T_int);
+ add_anchor_token(T_long);
+ add_anchor_token(T_new);
+ add_anchor_token(T_operator);
+ add_anchor_token(T_register);
+ add_anchor_token(T_reinterpret_cast);
+ add_anchor_token(T_restrict);
+ add_anchor_token(T_return);
+ add_anchor_token(T_short);
+ add_anchor_token(T_signed);
+ add_anchor_token(T_sizeof);
+ add_anchor_token(T_static);
+ add_anchor_token(T_static_cast);
+ add_anchor_token(T_struct);
+ add_anchor_token(T_switch);
+ add_anchor_token(T_template);
+ add_anchor_token(T_this);
+ add_anchor_token(T_throw);
+ add_anchor_token(T_true);
+ add_anchor_token(T_try);
+ add_anchor_token(T_typedef);
+ add_anchor_token(T_typeid);
+ add_anchor_token(T_typename);
+ add_anchor_token(T_typeof);
+ add_anchor_token(T_union);
+ add_anchor_token(T_unsigned);
+ add_anchor_token(T_using);
+ add_anchor_token(T_void);
+ add_anchor_token(T_volatile);
+ add_anchor_token(T_wchar_t);
+ add_anchor_token(T_while);
size_t const top = environment_top();
scope_t *old_scope = scope_push(&statement->compound.scope);
}
end_error:
+ rem_anchor_token(T_while);
+ rem_anchor_token(T_wchar_t);
+ rem_anchor_token(T_volatile);
+ rem_anchor_token(T_void);
+ rem_anchor_token(T_using);
+ rem_anchor_token(T_unsigned);
+ rem_anchor_token(T_union);
+ rem_anchor_token(T_typeof);
+ rem_anchor_token(T_typename);
+ rem_anchor_token(T_typeid);
+ rem_anchor_token(T_typedef);
+ rem_anchor_token(T_try);
+ rem_anchor_token(T_true);
+ rem_anchor_token(T_throw);
+ rem_anchor_token(T_this);
+ rem_anchor_token(T_template);
+ rem_anchor_token(T_switch);
+ rem_anchor_token(T_struct);
+ rem_anchor_token(T_static_cast);
+ rem_anchor_token(T_static);
+ rem_anchor_token(T_sizeof);
+ rem_anchor_token(T_signed);
+ rem_anchor_token(T_short);
+ rem_anchor_token(T_return);
+ rem_anchor_token(T_restrict);
+ rem_anchor_token(T_reinterpret_cast);
+ rem_anchor_token(T_register);
+ rem_anchor_token(T_operator);
+ rem_anchor_token(T_new);
+ rem_anchor_token(T_long);
+ rem_anchor_token(T_int);
+ rem_anchor_token(T_inline);
+ rem_anchor_token(T_if);
+ rem_anchor_token(T_goto);
+ rem_anchor_token(T_for);
+ rem_anchor_token(T_float);
+ rem_anchor_token(T_false);
+ rem_anchor_token(T_extern);
+ rem_anchor_token(T_enum);
+ rem_anchor_token(T_dynamic_cast);
+ rem_anchor_token(T_do);
+ rem_anchor_token(T_double);
+ rem_anchor_token(T_delete);
+ rem_anchor_token(T_default);
+ rem_anchor_token(T_continue);
+ rem_anchor_token(T_const_cast);
+ rem_anchor_token(T_const);
+ rem_anchor_token(T_class);
+ rem_anchor_token(T_char);
+ rem_anchor_token(T_case);
+ rem_anchor_token(T_break);
+ 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___func__);
+ 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___FUNCTION__);
+ rem_anchor_token(T__Imaginary);
+ rem_anchor_token(T__Complex);
+ rem_anchor_token(T__Bool);
+ rem_anchor_token(T_WIDE_STRING_LITERAL);
+ rem_anchor_token(T_WIDE_CHARACTER_CONSTANT);
+ rem_anchor_token(T_STRING_LITERAL);
+ rem_anchor_token(T_PLUSPLUS);
+ rem_anchor_token(T_MINUSMINUS);
+ rem_anchor_token(T_INTEGER);
+ rem_anchor_token(T_IDENTIFIER);
+ rem_anchor_token(T_FLOATINGPOINT);
+ rem_anchor_token(T_COLONCOLON);
+ rem_anchor_token(T_CHARACTER_CONSTANT);
+ rem_anchor_token('~');
+ rem_anchor_token('{');
+ rem_anchor_token('-');
+ rem_anchor_token('+');
+ rem_anchor_token('*');
+ rem_anchor_token('(');
+ rem_anchor_token('&');
+ rem_anchor_token('!');
rem_anchor_token('}');
assert(current_scope == &statement->compound.scope);
scope_pop(old_scope);
statement_t *statement = allocate_statement_zero(STATEMENT_ASM);
eat(T_asm);
- expect('(');
+ expect('(', end_error);
statement->asms.asm_text = parse_string_literals();
statement->base.next = unit->global_asm;
unit->global_asm = statement;
- expect(')');
- expect(';');
+ expect(')', end_error);
+ expect(';', end_error);
end_error:;
}
if (token.type == '{') {
next_token();
parse_externals();
- expect('}');
+ expect('}', end_error);
} else {
parse_external();
}
/* FALLTHROUGH */
default:
- errorf(HERE, "stray '%K' outside of function", &token);
+ errorf(HERE, "stray %K outside of function", &token);
if (token.type == '(' || token.type == '{' || token.type == '[')
eat_until_matching_token(token.type);
next_token();
if (token.type == T_EOF)
break;
- errorf(HERE, "stray '%K' outside of function", &token);
+ errorf(HERE, "stray %K outside of function", &token);
if (token.type == '(' || token.type == '{' || token.type == '[')
eat_until_matching_token(token.type);
next_token();