switch (token.type) {
case T___attribute__:
attribute = parse_attribute_gnu();
+ if (attribute == NULL)
+ continue;
break;
case T_asm:
if (iter == NULL) {
errorf(&designator->source_position,
"'%T' has no member named '%Y'", orig_type, symbol);
- goto failed;
+ return false;
}
assert(iter->kind == ENTITY_COMPOUND_MEMBER);
if (used_in_offsetof) {
errorf(&designator->source_position,
"offsetof designator '%Y' must not specify bitfield",
symbol);
- goto failed;
+ return false;
}
}
"[%E] designator used for non-array type '%T'",
array_index, orig_type);
}
- goto failed;
+ return false;
}
long index = fold_constant_to_int(array_index);
}
}
return true;
-
-failed:
- return false;
}
static void advance_current_object(type_path_t *path, size_t top_path_level)
case T_long:
if (type_specifiers & SPECIFIER_LONG_LONG) {
- errorf(HERE, "multiple type specifiers given");
+ errorf(HERE, "too many long type specifiers given");
} else if (type_specifiers & SPECIFIER_LONG) {
type_specifiers |= SPECIFIER_LONG_LONG;
} else {
next_token();
saw_error = true;
- if (la1_type == '&' || la1_type == '*')
- goto finish_specifiers;
continue;
}
/* ISO/IEC 14882:1998(E) §C.1.6:1 */
if (!(c_mode & _CXX))
type->unspecified_parameters = true;
- goto parameters_finished;
- }
-
- if (has_parameters()) {
+ } else if (has_parameters()) {
function_parameter_t **anchor = &type->parameters;
do {
switch (token.type) {
} while (next_if(','));
}
-
parameters_finished:
rem_anchor_token(')');
expect(')', end_error);
}
next_token();
break;
- case '(':
- /* §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);
- if (inner_types != NULL) {
- /* All later declarators only modify the return type */
- env->must_be_abstract = true;
- }
- rem_anchor_token(')');
- expect(')', end_error);
- } else if (!env->may_be_abstract) {
- errorf(HERE, "declarator must have a name");
- goto error_out;
+
+ case '(': {
+ /* Parenthesized declarator or function declarator? */
+ token_t const *const la1 = look_ahead(1);
+ switch (la1->type) {
+ case T_IDENTIFIER:
+ if (is_typedef_symbol(la1->symbol)) {
+ case ')':
+ /* §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. */
+ default:
+ /* Function declarator. */
+ if (!env->may_be_abstract) {
+ errorf(HERE, "function declarator must have a name");
+ goto error_out;
+ }
+ } else {
+ case '&':
+ case '(':
+ case '*':
+ case '[':
+ case T___attribute__: /* FIXME __attribute__ might also introduce a parameter of a function declarator. */
+ /* Paranthesized declarator. */
+ next_token();
+ add_anchor_token(')');
+ inner_types = parse_inner_declarator(env);
+ if (inner_types != NULL) {
+ /* All later declarators only modify the return type */
+ env->must_be_abstract = true;
+ }
+ rem_anchor_token(')');
+ expect(')', end_error);
+ }
+ break;
}
break;
+ }
+
default:
if (env->may_be_abstract)
break;
}
const function_parameter_t *parm = func_type->parameters;
if (parm != NULL) {
- type_t *const first_type = parm->type;
- if (!types_compatible(skip_typeref(first_type), type_int)) {
+ type_t *const first_type = skip_typeref(parm->type);
+ type_t *const first_type_unqual = get_unqualified_type(first_type);
+ if (!types_compatible(first_type_unqual, type_int)) {
warningf(pos,
"first argument of 'main' should be 'int', but is '%T'",
- first_type);
+ parm->type);
}
parm = parm->next;
if (parm != NULL) {
- type_t *const second_type = parm->type;
- if (!types_compatible(skip_typeref(second_type), type_char_ptr_ptr)) {
- warningf(pos, "second argument of 'main' should be 'char**', but is '%T'", second_type);
+ type_t *const second_type = skip_typeref(parm->type);
+ type_t *const second_type_unqual
+ = get_unqualified_type(second_type);
+ if (!types_compatible(second_type_unqual, type_char_ptr_ptr)) {
+ warningf(pos, "second argument of 'main' should be 'char**', but is '%T'",
+ parm->type);
}
parm = parm->next;
if (parm != NULL) {
- type_t *const third_type = parm->type;
- if (!types_compatible(skip_typeref(third_type), type_char_ptr_ptr)) {
- warningf(pos, "third argument of 'main' should be 'char**', but is '%T'", third_type);
+ type_t *const third_type = skip_typeref(parm->type);
+ type_t *const third_type_unqual
+ = get_unqualified_type(third_type);
+ if (!types_compatible(third_type_unqual, type_char_ptr_ptr)) {
+ warningf(pos, "third argument of 'main' should be 'char**', but is '%T'",
+ parm->type);
}
parm = parm->next;
if (parm != NULL)
literal->literal.value = token.literal;
size_t len = literal->literal.value.size;
- if (len != 1) {
+ if (len > 1) {
if (!GNU_MODE && !(c_mode & _C99)) {
errorf(HERE, "more than 1 character in character constant");
} else if (warning.multichar) {
literal->literal.value = token.literal;
size_t len = wstrlen(&literal->literal.value);
- if (len != 1) {
+ if (len > 1) {
warningf(HERE, "multi-character character constant");
}
return create_invalid_expression();
}
-/**
- * Check if the expression has the character type and issue a warning then.
- */
-static void check_for_char_index_type(const expression_t *expression)
-{
- type_t *const type = expression->base.type;
- const type_t *const base_type = skip_typeref(type);
-
- if (is_type_atomic(base_type, ATOMIC_TYPE_CHAR) &&
- warning.char_subscripts) {
- warningf(&expression->base.source_position,
- "array subscript has type '%T'", type);
- }
-}
-
static expression_t *parse_array_expression(expression_t *left)
{
- expression_t *expression = allocate_expression_zero(EXPR_ARRAY_ACCESS);
+ expression_t *const expr = allocate_expression_zero(EXPR_ARRAY_ACCESS);
+ array_access_expression_t *const arr = &expr->array_access;
eat('[');
add_anchor_token(']');
- expression_t *inside = parse_expression();
+ expression_t *const inside = parse_expression();
type_t *const orig_type_left = left->base.type;
type_t *const orig_type_inside = inside->base.type;
type_t *const type_left = skip_typeref(orig_type_left);
type_t *const type_inside = skip_typeref(orig_type_inside);
- type_t *return_type;
- array_access_expression_t *array_access = &expression->array_access;
+ expression_t *ref;
+ expression_t *idx;
+ type_t *idx_type;
+ type_t *res_type;
if (is_type_pointer(type_left)) {
- return_type = type_left->pointer.points_to;
- array_access->array_ref = left;
- array_access->index = inside;
- check_for_char_index_type(inside);
+ ref = left;
+ idx = inside;
+ idx_type = type_inside;
+ res_type = type_left->pointer.points_to;
+ goto check_idx;
} else if (is_type_pointer(type_inside)) {
- return_type = type_inside->pointer.points_to;
- array_access->array_ref = inside;
- array_access->index = left;
- array_access->flipped = true;
- check_for_char_index_type(left);
+ arr->flipped = true;
+ ref = inside;
+ idx = left;
+ idx_type = type_left;
+ res_type = type_inside->pointer.points_to;
+check_idx:
+ res_type = automatic_type_conversion(res_type);
+ if (is_type_atomic(idx_type, ATOMIC_TYPE_CHAR) && warning.char_subscripts) {
+ warningf(&idx->base.source_position, "array subscript has char type");
+ }
} else {
if (is_type_valid(type_left) && is_type_valid(type_inside)) {
errorf(HERE,
"array access on object with non-pointer types '%T', '%T'",
orig_type_left, orig_type_inside);
}
- return_type = type_error_type;
- array_access->array_ref = left;
- array_access->index = inside;
+ res_type = type_error_type;
+ ref = left;
+ idx = inside;
}
- expression->base.type = automatic_type_conversion(return_type);
+ arr->array_ref = ref;
+ arr->index = idx;
+ arr->base.type = res_type;
rem_anchor_token(']');
expect(']', end_error);
end_error:
- return expression;
+ return expr;
}
static expression_t *parse_typeprop(expression_kind_t const kind)