(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))) {
+ } else if (is_type_compound(type_left) && is_type_compound(type_right)) {
type_t *const unqual_type_left = get_unqualified_type(type_left);
type_t *const unqual_type_right = get_unqualified_type(type_right);
if (types_compatible(unqual_type_left, unqual_type_right)) {
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)
if (type != NULL && is_type_scalar(type)) {
sub = parse_scalar_initializer(type, env->must_be_constant);
} else {
- eat('{');
if (type == NULL) {
if (env->entity != NULL) {
errorf(HERE,
} else {
errorf(HERE, "extra brace group at end of initializer");
}
- } else
+ eat('{');
+ } else {
+ eat('{');
descend_into_subtype(path);
+ }
add_anchor_token('}');
sub = parse_sub_initializer(path, orig_type, top_path_level+1,
static compound_t *parse_compound_type_specifier(bool is_struct)
{
+ source_position_t const pos = *HERE;
eat(is_struct ? T_struct : T_union);
- symbol_t *symbol = NULL;
- compound_t *compound = NULL;
+ symbol_t *symbol = NULL;
+ entity_t *entity = NULL;
attribute_t *attributes = NULL;
if (token.type == T___attribute__) {
if (token.type == T_IDENTIFIER) {
/* the compound has a name, check if we have seen it already */
symbol = token.symbol;
+ entity = get_tag(symbol, kind);
next_token();
- entity_t *entity = get_tag(symbol, kind);
if (entity != NULL) {
- compound = &entity->compound;
- if (compound->base.parent_scope != current_scope &&
+ if (entity->base.parent_scope != current_scope &&
(token.type == '{' || token.type == ';')) {
/* we're in an inner scope and have a definition. Shadow
* existing definition in outer scope */
- compound = NULL;
- } else if (compound->complete && token.type == '{') {
- assert(symbol != NULL);
- errorf(HERE, "multiple definitions of '%s %Y' (previous definition %P)",
+ entity = NULL;
+ } else if (entity->compound.complete && token.type == '{') {
+ errorf(&pos, "multiple definitions of '%s %Y' (previous definition %P)",
is_struct ? "struct" : "union", symbol,
- &compound->base.source_position);
+ &entity->base.source_position);
/* clear members in the hope to avoid further errors */
- compound->members.entities = NULL;
+ entity->compound.members.entities = NULL;
}
}
} else if (token.type != '{') {
- if (is_struct) {
- parse_error_expected("while parsing struct type specifier",
- T_IDENTIFIER, '{', NULL);
- } else {
- parse_error_expected("while parsing union type specifier",
- T_IDENTIFIER, '{', NULL);
- }
+ char const *const msg =
+ is_struct ? "while parsing struct type specifier" :
+ "while parsing union type specifier";
+ parse_error_expected(msg, T_IDENTIFIER, '{', NULL);
return NULL;
}
- if (compound == NULL) {
- entity_t *entity = allocate_entity_zero(kind);
- compound = &entity->compound;
+ if (entity == NULL) {
+ entity = allocate_entity_zero(kind);
- compound->alignment = 1;
- compound->base.namespc = NAMESPACE_TAG;
- compound->base.source_position = token.source_position;
- compound->base.symbol = symbol;
- compound->base.parent_scope = current_scope;
+ entity->compound.alignment = 1;
+ entity->base.namespc = NAMESPACE_TAG;
+ entity->base.source_position = pos;
+ entity->base.symbol = symbol;
+ entity->base.parent_scope = current_scope;
if (symbol != NULL) {
environment_push(entity);
}
}
if (token.type == '{') {
- parse_compound_type_entries(compound);
+ parse_compound_type_entries(&entity->compound);
/* ISO/IEC 14882:1998(E) §7.1.3:5 */
if (symbol == NULL) {
assert(anonymous_entity == NULL);
- anonymous_entity = (entity_t*)compound;
+ anonymous_entity = entity;
}
}
if (attributes != NULL) {
- handle_entity_attributes(attributes, (entity_t*) compound);
+ handle_entity_attributes(attributes, entity);
}
- return compound;
+ return &entity->compound;
}
static void parse_enum_entries(type_t *const enum_type)
static type_t *parse_enum_specifier(void)
{
- entity_t *entity;
- symbol_t *symbol;
+ source_position_t const pos = *HERE;
+ entity_t *entity;
+ symbol_t *symbol;
eat(T_enum);
switch (token.type) {
case T_IDENTIFIER:
symbol = token.symbol;
+ entity = get_tag(symbol, ENTITY_ENUM);
next_token();
- entity = get_tag(symbol, ENTITY_ENUM);
if (entity != NULL) {
if (entity->base.parent_scope != current_scope &&
(token.type == '{' || token.type == ';')) {
* existing definition in outer scope */
entity = NULL;
} else if (entity->enume.complete && token.type == '{') {
- errorf(HERE, "multiple definitions of 'enum %Y' (previous definition %P)",
+ errorf(&pos, "multiple definitions of 'enum %Y' (previous definition %P)",
symbol, &entity->base.source_position);
}
}
if (entity == NULL) {
entity = allocate_entity_zero(ENTITY_ENUM);
entity->base.namespc = NAMESPACE_TAG;
- entity->base.source_position = token.source_position;
+ entity->base.source_position = pos;
entity->base.symbol = symbol;
entity->base.parent_scope = current_scope;
}
SPECIFIER_IMAGINARY = 1 << 18,
} specifiers_t;
-static type_t *create_builtin_type(symbol_t *const symbol,
- type_t *const real_type)
-{
- type_t *type = allocate_type_zero(TYPE_BUILTIN);
- type->builtin.symbol = symbol;
- type->builtin.real_type = real_type;
- return identify_new_type(type);
-}
-
static type_t *get_typedef_type(symbol_t *symbol)
{
entity_t *entity = get_entity(symbol, NAMESPACE_NORMAL);
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);
typedef struct construct_type_base_t {
construct_type_kind_t kind;
+ source_position_t pos;
construct_type_t *next;
} construct_type_base_t;
{
construct_type_t *const cons = obstack_alloc(&temp_obst, size);
memset(cons, 0, size);
- cons->kind = kind;
+ cons->kind = kind;
+ cons->base.pos = *HERE;
return cons;
}
/* §6.7.5.1 */
static construct_type_t *parse_pointer_declarator(void)
{
- eat('*');
-
construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_POINTER, sizeof(parsed_pointer_t));
+ eat('*');
cons->pointer.type_qualifiers = parse_type_qualifiers();
//cons->pointer.base_variable = base_variable;
/* ISO/IEC 14882:1998(E) §8.3.2 */
static construct_type_t *parse_reference_declarator(void)
{
- eat('&');
-
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));
+ eat('&');
return cons;
}
/* §6.7.5.2 */
static construct_type_t *parse_array_declarator(void)
{
- eat('[');
- add_anchor_token(']');
-
construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_ARRAY, sizeof(parsed_array_t));
parsed_array_t *const array = &cons->array;
+ eat('[');
+ add_anchor_token(']');
+
bool is_static = next_if(T_static);
type_qualifiers_t type_qualifiers = parse_type_qualifiers();
}
if (is_static && size == NULL)
- errorf(HERE, "static array parameters require a size");
+ errorf(&array->base.pos, "static array parameters require a size");
rem_anchor_token(']');
expect(']', end_error);
/* §6.7.5.3 */
static construct_type_t *parse_function_declarator(scope_t *scope)
{
+ construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_FUNCTION, sizeof(construct_function_type_t));
+
type_t *type = allocate_type_zero(TYPE_FUNCTION);
function_type_t *ftype = &type->function;
parse_parameters(ftype, scope);
- construct_type_t *const cons = allocate_declarator_zero(CONSTRUCT_FUNCTION, sizeof(construct_function_type_t));
cons->function.function_type = type;
return cons;
}
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;
{
construct_type_t *iter = construct_list;
for (; iter != NULL; iter = iter->base.next) {
+ source_position_t const* const pos = &iter->base.pos;
switch (iter->kind) {
case CONSTRUCT_INVALID:
break;
type_t *skipped_return_type = skip_typeref(type);
/* §6.7.5.3:1 */
if (is_type_function(skipped_return_type)) {
- errorf(HERE, "function returning function is not allowed");
+ errorf(pos, "function returning function is not allowed");
} else if (is_type_array(skipped_return_type)) {
- errorf(HERE, "function returning array is not allowed");
+ errorf(pos, "function returning array is not allowed");
} else {
if (skipped_return_type->base.qualifiers != 0 && warning.other) {
- warningf(HERE,
- "type qualifiers in return type of function type are meaningless");
+ warningf(pos, "type qualifiers in return type of function type are meaningless");
}
}
case CONSTRUCT_POINTER: {
if (is_type_reference(skip_typeref(type)))
- errorf(HERE, "cannot declare a pointer to reference");
+ errorf(pos, "cannot declare a pointer to reference");
parsed_pointer_t *pointer = &iter->pointer;
type = make_based_pointer_type(type, pointer->type_qualifiers, pointer->base_variable);
case CONSTRUCT_REFERENCE:
if (is_type_reference(skip_typeref(type)))
- errorf(HERE, "cannot declare a reference to reference");
+ errorf(pos, "cannot declare a reference to reference");
type = make_reference_type(type);
continue;
case CONSTRUCT_ARRAY: {
if (is_type_reference(skip_typeref(type)))
- errorf(HERE, "cannot declare an array of references");
+ errorf(pos, "cannot declare an array of references");
parsed_array_t *array = &iter->array;
type_t *array_type = allocate_type_zero(TYPE_ARRAY);
type_t *skipped_type = skip_typeref(type);
/* §6.7.5.2:1 */
if (is_type_incomplete(skipped_type)) {
- errorf(HERE, "array of incomplete type '%T' is not allowed", type);
+ errorf(pos, "array of incomplete type '%T' is not allowed", type);
} else if (is_type_function(skipped_type)) {
- errorf(HERE, "array of functions is not allowed");
+ errorf(pos, "array of functions is not allowed");
}
type = identify_new_type(array_type);
continue;
}
}
- internal_errorf(HERE, "invalid type construction found");
+ internal_errorf(pos, "invalid type construction found");
}
return type;
storage_class_t storage_class = specifiers->storage_class;
entity->declaration.declared_storage_class = storage_class;
- if (storage_class == STORAGE_CLASS_NONE && current_function != NULL)
+ if (storage_class == STORAGE_CLASS_NONE && current_function != NULL)
storage_class = STORAGE_CLASS_AUTO;
entity->declaration.storage_class = storage_class;
}
}
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)
} else {
unsigned old_storage_class = prev_decl->storage_class;
- if (warning.redundant_decls &&
+ if (warning.redundant_decls &&
is_definition &&
!prev_decl->used &&
!(prev_decl->modifiers & DM_USED) &&
entity_t *previous_entity = get_entity(symbol, NAMESPACE_NORMAL);
if (previous_entity == NULL
|| previous_entity->base.parent_scope != current_scope) {
- errorf(HERE, "expected declaration of a function parameter, found '%Y'",
+ errorf(&entity->base.source_position, "expected declaration of a function parameter, found '%Y'",
symbol);
return entity;
}
if (warning.aggregate_return &&
is_type_compound(skip_typeref(type->function.return_type))) {
- warningf(HERE, "function '%Y' returns an aggregate",
+ warningf(&ndeclaration->base.source_position, "function '%Y' returns an aggregate",
ndeclaration->base.symbol);
}
if (warning.traditional && !type->function.unspecified_parameters) {
- warningf(HERE, "traditional C rejects ISO C style function definition of function '%Y'",
+ warningf(&ndeclaration->base.source_position, "traditional C rejects ISO C style function definition of function '%Y'",
ndeclaration->base.symbol);
}
if (warning.old_style_definition && type->function.unspecified_parameters) {
- warningf(HERE, "old-style function definition '%Y'",
+ warningf(&ndeclaration->base.source_position, "old-style function definition '%Y'",
ndeclaration->base.symbol);
}
assert(entity->kind == ENTITY_FUNCTION);
assert(ndeclaration->kind == ENTITY_FUNCTION);
- function_t *function = &entity->function;
+ function_t *const function = &entity->function;
if (ndeclaration != entity) {
function->parameters = ndeclaration->function.parameters;
}
function_t *old_current_function = current_function;
entity_t *old_current_entity = current_entity;
current_function = function;
- current_entity = (entity_t*) function;
+ current_entity = entity;
current_parent = NULL;
goto_first = NULL;
assert(current_parent == NULL);
assert(current_function == function);
- assert(current_entity == (entity_t*) function);
+ assert(current_entity == entity);
current_entity = old_current_entity;
current_function = old_current_function;
label_pop_to(label_stack_top);
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");
}
static expression_t *parse_reference(void)
{
- entity_t *entity = parse_qualified_identifier();
+ source_position_t const pos = token.source_position;
+ entity_t *const entity = parse_qualified_identifier();
type_t *orig_type;
if (is_declaration(entity)) {
if (entity->kind == ENTITY_ENUM_VALUE)
kind = EXPR_REFERENCE_ENUM_VALUE;
- expression_t *expression = allocate_expression_zero(kind);
- expression->reference.entity = entity;
- expression->base.type = type;
+ expression_t *expression = allocate_expression_zero(kind);
+ expression->base.source_position = pos;
+ expression->base.type = type;
+ expression->reference.entity = entity;
/* this declaration is used */
if (is_declaration(entity)) {
if (warning.init_self && entity == current_init_decl && !in_type_prop
&& entity->kind == ENTITY_VARIABLE) {
current_init_decl = NULL;
- warningf(HERE, "variable '%#T' is initialized by itself",
+ warningf(&pos, "variable '%#T' is initialized by itself",
entity->declaration.type, entity->base.symbol);
}
*/
static expression_t *parse_cast(void)
{
- add_anchor_token(')');
-
source_position_t source_position = token.source_position;
+ eat('(');
+ add_anchor_token(')');
+
type_t *type = parse_typename();
rem_anchor_token(')');
*/
static expression_t *parse_statement_expression(void)
{
- add_anchor_token(')');
-
expression_t *expression = allocate_expression_zero(EXPR_STATEMENT);
+ eat('(');
+ add_anchor_token(')');
+
statement_t *statement = parse_compound_statement(true);
statement->compound.stmt_expr = true;
expression->statement.statement = statement;
*/
static expression_t *parse_parenthesized_expression(void)
{
- eat('(');
-
- switch (token.type) {
+ token_t const* const la1 = look_ahead(1);
+ switch (la1->type) {
case '{':
/* gcc extension: a statement expression */
return parse_statement_expression();
+ case T_IDENTIFIER:
+ if (is_typedef_symbol(la1->symbol)) {
TYPE_QUALIFIERS
TYPE_SPECIFIERS
- return parse_cast();
- case T_IDENTIFIER:
- if (is_typedef_symbol(token.symbol)) {
return parse_cast();
}
}
+ eat('(');
add_anchor_token(')');
expression_t *result = parse_expression();
result->base.parenthesized = true;
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_integer(idx_type)) {
+ errorf(&idx->base.source_position, "array subscript must have integer type");
+ } else 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)
/* report exact scope in error messages (like "in argument 3") */
char buf[64];
snprintf(buf, sizeof(buf), "call argument %u", pos);
- report_assign_error(error, expected_type, arg_expr, buf,
- &arg_expr->base.source_position);
+ report_assign_error(error, expected_type, arg_expr, buf,
+ &arg_expr->base.source_position);
} else if (warning.traditional || warning.conversion) {
type_t *const promoted_type = get_default_promoted_type(arg_type);
if (!types_compatible(expected_type_skip, promoted_type) &&
}
if (parameter != NULL) {
- errorf(HERE, "too few arguments to function '%E'", expression);
+ errorf(&expression->base.source_position, "too few arguments to function '%E'", expression);
} else if (argument != NULL && !function_type->variadic) {
- errorf(HERE, "too many arguments to function '%E'", expression);
+ errorf(&argument->expression->base.source_position, "too many arguments to function '%E'", expression);
}
}
if (entity->declaration.storage_class == STORAGE_CLASS_REGISTER
&& !may_be_register) {
errorf(&expression->base.source_position,
- "address of register %s '%Y' requested",
- get_entity_kind_name(entity->kind), entity->base.symbol);
+ "address of register %s '%Y' requested",
+ get_entity_kind_name(entity->kind), entity->base.symbol);
}
if (entity->kind == ENTITY_VARIABLE) {
expression->base.type = arithmetic_type;
}
+static void semantic_binexpr_integer(binary_expression_t *const expression)
+{
+ expression_t *const left = expression->left;
+ expression_t *const right = expression->right;
+ type_t *const orig_type_left = left->base.type;
+ type_t *const orig_type_right = right->base.type;
+ type_t *const type_left = skip_typeref(orig_type_left);
+ type_t *const type_right = skip_typeref(orig_type_right);
+
+ if (!is_type_integer(type_left) || !is_type_integer(type_right)) {
+ /* TODO: improve error message */
+ if (is_type_valid(type_left) && is_type_valid(type_right)) {
+ errorf(&expression->base.source_position,
+ "operation needs integer types");
+ }
+ return;
+ }
+
+ type_t *const result_type = semantic_arithmetic(type_left, type_right);
+ expression->left = create_implicit_cast(left, result_type);
+ expression->right = create_implicit_cast(right, result_type);
+ expression->base.type = result_type;
+}
+
static void warn_div_by_zero(binary_expression_t const *const expression)
{
if (!warning.div_by_zero ||
type_t *const type_left = skip_typeref(orig_type_left);
if (!is_lvalue(left)) {
- errorf(HERE, "left hand side '%E' of assignment is not an lvalue",
+ errorf(&left->base.source_position, "left hand side '%E' of assignment is not an lvalue",
left);
return false;
}
if (left->kind == EXPR_REFERENCE
&& left->reference.entity->kind == ENTITY_FUNCTION) {
- errorf(HERE, "cannot assign to function '%E'", left);
+ errorf(&left->base.source_position, "cannot assign to function '%E'", left);
return false;
}
if (is_type_array(type_left)) {
- errorf(HERE, "cannot assign to array '%E'", left);
+ errorf(&left->base.source_position, "cannot assign to array '%E'", left);
return false;
}
if (type_left->base.qualifiers & TYPE_QUALIFIER_CONST) {
- errorf(HERE, "assignment to readonly location '%E' (type '%T')", left,
+ errorf(&left->base.source_position, "assignment to read-only location '%E' (type '%T')", left,
orig_type_left);
return false;
}
if (is_type_incomplete(type_left)) {
- errorf(HERE, "left-hand side '%E' of assignment has incomplete type '%T'",
+ errorf(&left->base.source_position, "left-hand side '%E' of assignment has incomplete type '%T'",
left, orig_type_left);
return false;
}
if (is_type_compound(type_left) && has_const_fields(&type_left->compound)) {
- errorf(HERE, "cannot assign to '%E' because compound type '%T' has readonly fields",
+ errorf(&left->base.source_position, "cannot assign to '%E' because compound type '%T' has read-only fields",
left, orig_type_left);
return false;
}
CREATE_BINEXPR_PARSER(T_GREATEREQUAL, EXPR_BINARY_GREATEREQUAL, PREC_SHIFT, semantic_comparison)
CREATE_BINEXPR_PARSER(T_EXCLAMATIONMARKEQUAL, EXPR_BINARY_NOTEQUAL, PREC_RELATIONAL, semantic_comparison)
CREATE_BINEXPR_PARSER(T_EQUALEQUAL, EXPR_BINARY_EQUAL, PREC_RELATIONAL, semantic_comparison)
-CREATE_BINEXPR_PARSER('&', EXPR_BINARY_BITWISE_AND, PREC_EQUALITY, semantic_binexpr_arithmetic)
-CREATE_BINEXPR_PARSER('^', EXPR_BINARY_BITWISE_XOR, PREC_AND, semantic_binexpr_arithmetic)
-CREATE_BINEXPR_PARSER('|', EXPR_BINARY_BITWISE_OR, PREC_XOR, semantic_binexpr_arithmetic)
+CREATE_BINEXPR_PARSER('&', EXPR_BINARY_BITWISE_AND, PREC_EQUALITY, semantic_binexpr_integer)
+CREATE_BINEXPR_PARSER('^', EXPR_BINARY_BITWISE_XOR, PREC_AND, semantic_binexpr_integer)
+CREATE_BINEXPR_PARSER('|', EXPR_BINARY_BITWISE_OR, PREC_XOR, semantic_binexpr_integer)
CREATE_BINEXPR_PARSER(T_ANDAND, EXPR_BINARY_LOGICAL_AND, PREC_OR, semantic_logical_op)
CREATE_BINEXPR_PARSER(T_PIPEPIPE, EXPR_BINARY_LOGICAL_OR, PREC_LOGICAL_AND, semantic_logical_op)
CREATE_BINEXPR_PARSER('=', EXPR_BINARY_ASSIGN, PREC_ASSIGNMENT, semantic_binexpr_assign)
* @param precedence the precedence of the operator
*/
static void register_infix_parser(parse_expression_infix_function parser,
- int token_type, precedence_t precedence)
+ int token_type, precedence_t precedence)
{
expression_parser_function_t *entry = &expression_parsers[token_type];
default:
inner_stmt = parse_statement();
- if (inner_stmt->kind == STATEMENT_DECLARATION) {
+ /* ISO/IEC 14882:1998(E) §6:1/§6.7 Declarations are statements */
+ if (inner_stmt->kind == STATEMENT_DECLARATION && !(c_mode & _CXX)) {
errorf(&inner_stmt->base.source_position, "declaration after %s", label_kind);
}
break;
}
} else {
assign_error_t error = semantic_assign(return_type, return_value);
- report_assign_error(error, return_type, return_value, "'return'",
- pos);
+ report_assign_error(error, return_type, return_value, "'return'",
+ pos);
}
return_value = create_implicit_cast(return_value, return_type);
/* check for returning address of a local var */
if (warning.other && return_value != NULL
- && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
+ && return_value->base.kind == EXPR_UNARY_TAKE_ADDRESS) {
const expression_t *expression = return_value->unary.value;
if (expression_is_local_variable(expression)) {
warningf(pos, "function returns address of local variable");
/* ISO/IEC 14882:1998(E) §6.6.3:3 */
if (c_mode & _CXX || strict_mode) {
errorf(pos,
- "'return' without value, in function returning non-void");
+ "'return' without value, in function returning non-void");
} else {
warningf(pos,
- "'return' without value, in function returning non-void");
+ "'return' without value, in function returning non-void");
}
}
statement->returns.value = return_value;
static void parse_linkage_specification(void)
{
eat(T_extern);
- assert(token.type == T_STRING_LITERAL);
const char *linkage = parse_string_literals().begin;
init_expression_parsers();
obstack_init(&temp_obst);
-
- symbol_t *const va_list_sym = symbol_table_insert("__builtin_va_list");
- type_valist = create_builtin_type(va_list_sym, type_void_ptr);
}
/**