main: rework preprocessor invocation
[cparser] / format_check.c
index f1134e2..4c1d670 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <ctype.h>
 
+#include "adt/strutil.h"
 #include "adt/util.h"
 #include "format_check.h"
 #include "symbol_t.h"
@@ -108,7 +109,7 @@ static int internal_check_printf_format(const expression_t *fmt_expr,
                                         const call_argument_t *arg,
                                         const format_spec_t *spec)
 {
-       while (fmt_expr->kind == EXPR_UNARY_CAST_IMPLICIT) {
+       while (fmt_expr->kind == EXPR_UNARY_CAST) {
                fmt_expr = fmt_expr->unary.value;
        }
 
@@ -126,12 +127,11 @@ 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;
@@ -143,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;
 
@@ -321,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;
@@ -521,7 +521,7 @@ too_few_args:
                                }
                        } else if (get_unqualified_type(arg_skip) == expected_type_skip) {
                                goto next_arg;
-                       } else if (arg->expression->kind == EXPR_UNARY_CAST_IMPLICIT) {
+                       } else if (arg->expression->kind == EXPR_UNARY_CAST) {
                                expression_t const *const expr        = arg->expression->unary.value;
                                type_t             *const unprom_type = skip_typeref(expr->base.type);
                                if (get_unqualified_type(unprom_type) == expected_type_skip) {
@@ -534,7 +534,7 @@ 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);
+                               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:
@@ -595,16 +595,15 @@ static void check_scanf_format(const call_argument_t *arg,
        }
 
        const expression_t *fmt_expr = arg->expression;
-       if (fmt_expr->kind == EXPR_UNARY_CAST_IMPLICIT) {
+       if (fmt_expr->kind == EXPR_UNARY_CAST) {
                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 */
@@ -842,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': {
@@ -915,7 +914,7 @@ 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);
+                               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:
@@ -1003,7 +1002,7 @@ void check_format(const call_expression_t *const call)
         */
        const char *const name = entity->base.symbol->string;
        for (size_t i = 0; i < lengthof(builtin_table); ++i) {
-               if (strcmp(name, builtin_table[i].name) == 0) {
+               if (streq(name, builtin_table[i].name)) {
                        switch (builtin_table[i].fmt_kind) {
                        case FORMAT_PRINTF:
                                check_printf_format(arg, &builtin_table[i]);