Print constant suffixes and properly print floats.
[cparser] / parser.c
index c1024ea..443946e 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -1092,6 +1092,7 @@ static type_t *make_global_typedef(const char *name, type_t *type)
        declaration->type                   = type;
        declaration->symbol                 = symbol;
        declaration->source_position        = builtin_source_position;
+       declaration->implicit               = true;
 
        record_declaration(declaration);
 
@@ -3060,6 +3061,20 @@ end_error:
        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;
@@ -3253,13 +3268,21 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
                                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;
@@ -3278,8 +3301,7 @@ static void parse_declaration_specifiers(declaration_specifiers_t *specifiers)
        }
 
 finish_specifiers:
-
-       if (type == NULL) {
+       if (type == NULL || (saw_error && type_specifiers != 0)) {
                atomic_type_kind_t atomic_type;
 
                /* match valid basic types */
@@ -3581,9 +3603,10 @@ static declaration_t *parse_parameters(function_type_t *type)
        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;
@@ -5662,6 +5685,7 @@ static declaration_t *create_implicit_function(symbol_t *symbol,
        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;
@@ -5852,9 +5876,11 @@ static expression_t *parse_reference(void)
        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);
                        }
@@ -5863,11 +5889,11 @@ static expression_t *parse_reference(void)
                                                               &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! */
@@ -5900,44 +5926,49 @@ static expression_t *parse_reference(void)
        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;
@@ -5982,13 +6013,13 @@ static expression_t *parse_cast(void)
        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();
@@ -9098,15 +9129,25 @@ static statement_t *intern_parse_statement(void)
        /* 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.