Print constant suffixes and properly print floats.
[cparser] / parser.c
index aebb7e8..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;
@@ -5224,11 +5247,10 @@ static void parse_external_declaration(void)
                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
@@ -5663,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;
@@ -5853,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);
                        }
@@ -5864,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! */
@@ -5901,48 +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)
 {
-       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;
@@ -5987,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();
@@ -6874,10 +6900,10 @@ static expression_t *parse_call_expression(unsigned precedence,
 
        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;
@@ -7357,16 +7383,22 @@ static void semantic_binexpr_arithmetic(binary_expression_t *expression)
        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)
@@ -7643,11 +7675,7 @@ static void semantic_arithmetic_assign(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)
@@ -9101,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.