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;
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)
{
+ 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 *dest_type = skip_typeref(orig_dest_type);
- type_t const *orig_type = skip_typeref(orig_type_right);
- source_position_t const *pos = &expression->base.source_position;
+ 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;
- 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) &&
- is_type_valid(orig_type)) {
- errorf(pos, "cannot convert type '%T' to a pointer type", orig_type_right);
- return false;
- }
- } else if (!is_type_scalar(dest_type) && is_type_valid(dest_type)) {
+ /* 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;
+ }
+
+ 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) && is_type_valid(orig_type)) {
+ }
+
+ 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 &&
- 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);
+ 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);
+ 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();
/* 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.