ast2firm: Factorise code to convert a value to its storage type.
[cparser] / format_check.c
index 5580d91..bbb47e3 100644 (file)
@@ -94,7 +94,7 @@ static const char* get_length_modifier_name(const format_length_modifier_t mod)
        return names[mod];
 }
 
-static void warn_invalid_length_modifier(const source_position_t *pos,
+static void warn_invalid_length_modifier(const position_t *pos,
                                          const format_length_modifier_t mod,
                                          const utf32 conversion)
 {
@@ -127,15 +127,14 @@ static int internal_check_printf_format(const expression_t *fmt_expr,
                return nt > nf ? nt : nf;
        }
 
-       if (fmt_expr->kind != EXPR_STRING_LITERAL
-                       && fmt_expr->kind != EXPR_WIDE_STRING_LITERAL)
+       if (fmt_expr->kind != EXPR_STRING_LITERAL)
                return -1;
 
-       const char *string = fmt_expr->literal.value.begin;
-       size_t      size   = fmt_expr->literal.value.size;
+       const char *string = fmt_expr->string_literal.value.begin;
+       size_t      size   = fmt_expr->string_literal.value.size;
        const char *c      = string;
 
-       const source_position_t *pos = &fmt_expr->base.source_position;
+       const position_t *pos = &fmt_expr->base.pos;
        unsigned num_fmt  = 0;
        unsigned num_args = 0;
        char     fmt;
@@ -144,10 +143,6 @@ static int internal_check_printf_format(const expression_t *fmt_expr,
                        continue;
                fmt = *(++c);
 
-               if (fmt == '\0') {
-                       warningf(WARN_FORMAT, pos, "dangling %% in format string");
-                       break;
-               }
                if (fmt == '%')
                        continue;
 
@@ -322,6 +317,10 @@ break_fmt_flags:
                                break;
                }
 
+               if (fmt == '\0') {
+                       warningf(WARN_FORMAT, pos, "dangling %% in format string");
+                       break;
+               }
 
                type_t            *expected_type;
                type_qualifiers_t  expected_qual = TYPE_QUALIFIER_NONE;
@@ -533,9 +532,9 @@ too_few_args:
                                }
                        }
                        if (is_type_valid(arg_skip)) {
-                               source_position_t const *const apos = &arg->expression->base.source_position;
-                               char              const *const mod  = get_length_modifier_name(fmt_mod);
-                               warningf(WARN_FORMAT, apos, "argument type '%T' does not match conversion specifier '%%%s%c' at position %u", arg_type, mod, (char)fmt, num_fmt);
+                               position_t const *const apos = &arg->expression->base.pos;
+                               char       const *const mod  = get_length_modifier_name(fmt_mod);
+                               warningf(WARN_FORMAT, apos, "conversion '%%%s%c' at position %u specifies type '%T' but the argument has type '%T'", mod, (char)fmt, num_fmt, expected_type, arg_type);
                        }
                }
 next_arg:
@@ -576,7 +575,7 @@ static void check_printf_format(call_argument_t const *arg,
        for (; arg != NULL; arg = arg->next)
                ++num_args;
        if (num_args > (size_t)num_fmt) {
-               source_position_t const *const pos = &fmt_expr->base.source_position;
+               position_t const *const pos = &fmt_expr->base.pos;
                warningf(WARN_FORMAT, pos, "%u argument%s but only %u format specifier%s", num_args, num_args != 1 ? "s" : "", num_fmt,  num_fmt  != 1 ? "s" : "");
        }
 }
@@ -600,19 +599,18 @@ static void check_scanf_format(const call_argument_t *arg,
                fmt_expr = fmt_expr->unary.value;
        }
 
-       if (fmt_expr->kind != EXPR_STRING_LITERAL
-                       && fmt_expr->kind != EXPR_WIDE_STRING_LITERAL)
+       if (fmt_expr->kind != EXPR_STRING_LITERAL)
                return;
 
-       const char *string = fmt_expr->literal.value.begin;
-       size_t      size   = fmt_expr->literal.value.size;
+       const char *string = fmt_expr->string_literal.value.begin;
+       size_t      size   = fmt_expr->string_literal.value.size;
        const char *c      = string;
 
        /* find the real args */
        for (; idx < spec->arg_idx && arg != NULL; ++idx)
                arg = arg->next;
 
-       const source_position_t *pos = &fmt_expr->base.source_position;
+       const position_t *pos = &fmt_expr->base.pos;
        unsigned num_fmt = 0;
        char     fmt;
        for (fmt = *c; fmt != '\0'; fmt = *(++c)) {
@@ -843,7 +841,7 @@ check_c_width:
                                warn_invalid_length_modifier(pos, fmt_mod, fmt);
                                goto next_arg;
                        }
-                       expected_type = type_void_ptr;
+                       expected_type = type_void;
                        break;
 
                case 'n': {
@@ -914,9 +912,9 @@ too_few_args:
                        }
 error_arg_type:
                        if (is_type_valid(arg_skip)) {
-                               source_position_t const *const apos = &arg->expression->base.source_position;
-                               char              const *const mod  = get_length_modifier_name(fmt_mod);
-                               warningf(WARN_FORMAT, apos, "argument type '%T' does not match conversion specifier '%%%s%c' at position %u", arg_type, mod, (char)fmt, num_fmt);
+                               position_t const *const apos = &arg->expression->base.pos;
+                               char       const *const mod  = get_length_modifier_name(fmt_mod);
+                               warningf(WARN_FORMAT, apos, "conversion '%%%s%c' at position %u specifies type '%T*' but the argument has type '%T'", mod, (char)fmt, num_fmt, expected_type, arg_type);
                        }
                }
 next_arg: