declaration->type = type;
declaration->symbol = symbol;
declaration->source_position = builtin_source_position;
+ declaration->implicit = true;
record_declaration(declaration);
return;
}
+static declaration_t *create_error_declaration(symbol_t *symbol, storage_class_tag_t storage_class)
+{
+ declaration_t *const decl = allocate_declaration_zero();
+ decl->source_position = *HERE;
+ decl->storage_class =
+ storage_class != STORAGE_CLASS_NONE || scope == global_scope ?
+ storage_class : STORAGE_CLASS_AUTO;
+ decl->declared_storage_class = decl->storage_class;
+ decl->symbol = symbol;
+ decl->implicit = true;
+ record_declaration(decl);
+ return decl;
+}
+
static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
{
type_t *type = NULL;
switch (la1_type) {
DECLARATION_START
case T_IDENTIFIER:
- case '*':
+ case '*': {
errorf(HERE, "%K does not name a type", &token);
+
+ declaration_t *const decl =
+ create_error_declaration(token.v.symbol, STORAGE_CLASS_TYPEDEF);
+
+ type = allocate_type_zero(TYPE_TYPEDEF, HERE);
+ type->typedeft.declaration = decl;
+
next_token();
saw_error = true;
if (la1_type == '*')
goto finish_specifiers;
continue;
+ }
default:
goto finish_specifiers;
}
finish_specifiers:
-
- if (type == NULL) {
+ if (type == NULL || (saw_error && type_specifiers != 0)) {
atomic_type_kind_t atomic_type;
/* match valid basic types */
add_anchor_token(')');
int saved_comma_state = save_and_reset_anchor_state(',');
- if (token.type == T_IDENTIFIER) {
- symbol_t *symbol = token.v.symbol;
- if (!is_typedef_symbol(symbol)) {
+ if (token.type == T_IDENTIFIER &&
+ !is_typedef_symbol(token.v.symbol)) {
+ token_type_t la1_type = look_ahead(1)->type;
+ if (la1_type == ',' || la1_type == ')') {
type->kr_style_parameters = true;
declarations = parse_identifier_list();
goto parameters_finished;
return;
}
- if (warning.aggregate_return) {
- const type_t *return_type = type->function.return_type;
- if (is_type_compound(return_type))
- warningf(HERE, "function '%Y' returns an aggregate",
- ndeclaration->symbol);
+ if (warning.aggregate_return &&
+ is_type_compound(skip_typeref(type->function.return_type))) {
+ warningf(HERE, "function '%Y' returns an aggregate",
+ ndeclaration->symbol);
}
/* § 6.7.5.3 (14) a function definition with () means no
declaration->type = type;
declaration->symbol = symbol;
declaration->source_position = *source_position;
+ declaration->implicit = true;
bool strict_prototypes_old = warning.strict_prototypes;
warning.strict_prototypes = false;
next_token();
if (declaration == NULL) {
- if (! strict_mode && token.type == '(') {
- /* an implicitly defined function */
- if (warning.implicit_function_declaration) {
+ if (token.type == '(') {
+ /* an implicitly declared function */
+ if (strict_mode) {
+ errorf(HERE, "unknown symbol '%Y' found.", symbol);
+ } else if (warning.implicit_function_declaration) {
warningf(HERE, "implicit declaration of function '%Y'",
symbol);
}
&source_position);
} else {
errorf(HERE, "unknown symbol '%Y' found.", symbol);
- return create_invalid_expression();
+ declaration = create_error_declaration(symbol, STORAGE_CLASS_NONE);
}
}
- type_t *type = declaration->type;
+ type_t *type = declaration->type;
/* we always do the auto-type conversions; the & and sizeof parser contains
* code to revert this! */
return expression;
}
-static bool semantic_cast(expression_t *expression, type_t *orig_dest_type)
+static bool semantic_cast(expression_t *cast)
{
- type_t *orig_type_right = expression->base.type;
- const type_t *dest_type = skip_typeref(orig_dest_type);
- const type_t *orig_type = skip_typeref(orig_type_right);
-
- if (!is_type_valid(dest_type) || !is_type_valid(orig_type))
- return true;
+ expression_t *expression = cast->unary.value;
+ type_t *orig_dest_type = cast->base.type;
+ type_t *orig_type_right = expression->base.type;
+ type_t const *dst_type = skip_typeref(orig_dest_type);
+ type_t const *src_type = skip_typeref(orig_type_right);
+ source_position_t const *pos = &cast->base.source_position;
/* §6.5.4 A (void) cast is explicitly permitted, more for documentation than for utility. */
- if (dest_type == type_void)
+ if (dst_type == type_void)
return true;
- /* TODO check if explicit cast is allowed and issue warnings/errors */
- if (is_type_pointer(dest_type)) {
- /* only integer and pointer can be casted to pointer */
- if (! is_type_pointer(orig_type) && ! is_type_integer(orig_type)) {
- errorf(HERE, "cannot convert type '%T' to a pointer type", orig_type_right);
- return false;
- }
+ /* only integer and pointer can be casted to pointer */
+ if (is_type_pointer(dst_type) &&
+ !is_type_pointer(src_type) &&
+ !is_type_integer(src_type) &&
+ is_type_valid(src_type)) {
+ errorf(pos, "cannot convert type '%T' to a pointer type", orig_type_right);
+ return false;
}
- else if (!is_type_scalar(dest_type)) {
- errorf(HERE, "conversion to non-scalar type '%T' requested", orig_dest_type);
+
+ if (!is_type_scalar(dst_type) && is_type_valid(dst_type)) {
+ errorf(pos, "conversion to non-scalar type '%T' requested", orig_dest_type);
return false;
}
- else if (!is_type_scalar(orig_type)) {
- errorf(HERE, "conversion from non-scalar type '%T' requested", orig_type_right);
+
+ if (!is_type_scalar(src_type) && is_type_valid(src_type)) {
+ errorf(pos, "conversion from non-scalar type '%T' requested", orig_type_right);
return false;
}
- if (warning.cast_qual) {
- if (is_type_pointer(orig_type) &&
- is_type_pointer(dest_type)) {
- type_t *src = skip_typeref(orig_type->pointer.points_to);
- type_t *dst = skip_typeref(dest_type->pointer.points_to);
- unsigned missing_qualifiers
- = src->base.qualifiers & ~dst->base.qualifiers;
- if (missing_qualifiers != 0) {
- warningf(HERE,
- "cast discards qualifiers '%Q' in pointer target type of '%T'",
- missing_qualifiers, orig_type_right);
- }
+ if (warning.cast_qual &&
+ is_type_pointer(src_type) &&
+ is_type_pointer(dst_type)) {
+ type_t *src = skip_typeref(src_type->pointer.points_to);
+ type_t *dst = skip_typeref(dst_type->pointer.points_to);
+ unsigned missing_qualifiers =
+ src->base.qualifiers & ~dst->base.qualifiers;
+ if (missing_qualifiers != 0) {
+ warningf(pos,
+ "cast discards qualifiers '%Q' in pointer target type of '%T'",
+ missing_qualifiers, orig_type_right);
}
}
return true;
cast->base.source_position = source_position;
expression_t *value = parse_sub_expression(20);
-
- if (! semantic_cast(value, type))
- goto end_error;
-
cast->base.type = type;
cast->unary.value = value;
+ if (! semantic_cast(cast)) {
+ /* TODO: record the error in the AST. else it is impossible to detect it */
+ }
+
return cast;
end_error:
return create_invalid_expression();
check_format(&result->call);
- if (warning.aggregate_return) {
- const type_t *return_type = function_type->return_type;
- if (is_type_compound(return_type))
- warningf(&result->base.source_position, "function call has aggregate value");
+ if (warning.aggregate_return &&
+ is_type_compound(skip_typeref(function_type->return_type))) {
+ warningf(&result->base.source_position,
+ "function call has aggregate value");
}
return result;
expression->base.type = arithmetic_type;
}
+static void warn_div_by_zero(binary_expression_t const *const expression)
+{
+ if (warning.div_by_zero &&
+ is_type_integer(expression->base.type) &&
+ is_constant_expression(expression->right) &&
+ fold_constant(expression->right) == 0) {
+ warningf(&expression->base.source_position, "division by zero");
+ }
+}
+
/**
* Check the semantic restrictions for a div/mod expression.
*/
static void semantic_divmod_arithmetic(binary_expression_t *expression) {
semantic_binexpr_arithmetic(expression);
- if (warning.div_by_zero && is_type_integer(expression->base.type)) {
- if (is_constant_expression(expression->right) &&
- fold_constant(expression->right) == 0)
- warningf(&expression->base.source_position, "division by zero");
- }
+ warn_div_by_zero(expression);
}
static void semantic_shift_op(binary_expression_t *expression)
static void semantic_divmod_assign(binary_expression_t *expression)
{
semantic_arithmetic_assign(expression);
- if (warning.div_by_zero && is_type_integer(expression->base.type)) {
- if (is_constant_expression(expression->right) &&
- fold_constant(expression->right) == 0)
- warningf(&expression->base.source_position, "division by zero");
- }
+ warn_div_by_zero(expression);
}
static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression)
/* declaration or statement */
add_anchor_token(';');
switch (token.type) {
- case T_IDENTIFIER:
- if (look_ahead(1)->type == ':') {
+ case T_IDENTIFIER: {
+ token_type_t la1_type = (token_type_t)look_ahead(1)->type;
+ if (la1_type == ':') {
statement = parse_label_statement();
} else if (is_typedef_symbol(token.v.symbol)) {
statement = parse_declaration_statement();
- } else {
- statement = parse_expression_statement();
+ } else switch (la1_type) {
+ DECLARATION_START
+ case T_IDENTIFIER:
+ case '*':
+ statement = parse_declaration_statement();
+ break;
+
+ default:
+ statement = parse_expression_statement();
+ break;
}
break;
+ }
case T___extension__:
/* This can be a prefix to a declaration or an expression statement.