add license prefix
[cparser] / format_check.c
index 7710353..4fad47a 100644 (file)
@@ -142,7 +142,7 @@ break_fmt_flags:
                                        warningf(pos, "missing argument for '*' field width in conversion specification");
                                        return;
                                }
-                               const type_t *const arg_type = arg->expression->base.datatype;
+                               const type_t *const arg_type = arg->expression->base.type;
                                if (arg_type != type_int) {
                                        warningf(pos, "argument for '*' field width in conversion specification is not an 'int', but an '%T'", arg_type);
                                }
@@ -162,7 +162,7 @@ break_fmt_flags:
                                        warningf(pos, "missing argument for '*' precision in conversion specification");
                                        return;
                                }
-                               const type_t *const arg_type = arg->expression->base.datatype;
+                               const type_t *const arg_type = arg->expression->base.type;
                                if (arg_type != type_int) {
                                        warningf(pos, "argument for '*' precision in conversion specification is not an 'int', but an '%T'", arg_type);
                                }
@@ -211,8 +211,9 @@ break_fmt_flags:
                        break;
                }
 
-               const type_t   *expected_type;
-               format_flags_t  allowed_flags;
+               const type_t      *expected_type;
+               type_qualifiers_t  expected_qual = TYPE_QUALIFIER_NONE;
+               format_flags_t     allowed_flags;
                switch (*fmt) {
                        case 'd':
                        case 'i':
@@ -307,18 +308,20 @@ eval_fmt_mod_unsigned:
                                        goto next_arg;
                                }
                                expected_type = type_wchar_t_ptr;
+                               expected_qual = TYPE_QUALIFIER_CONST;
                                allowed_flags = FMT_FLAG_NONE;
                                break;
 
                        case 's':
                                switch (fmt_mod) {
-                                       case FMT_MOD_NONE: expected_type = type_string;      break;
+                                       case FMT_MOD_NONE: expected_type = type_char_ptr;    break;
                                        case FMT_MOD_l:    expected_type = type_wchar_t_ptr; break;
 
                                        default:
                                                warn_invalid_length_modifier(pos, fmt_mod, *fmt);
                                                goto next_arg;
                                }
+                               expected_qual = TYPE_QUALIFIER_CONST;
                                allowed_flags = FMT_FLAG_NONE;
                                break;
 
@@ -364,27 +367,29 @@ eval_fmt_mod_unsigned:
                        return;
                }
 
-               type_t *const arg_type = arg->expression->base.datatype;
-               if (is_type_pointer(expected_type)) {
-                       type_t *const arg_skip = skip_typeref(arg_type);
-                       if (is_type_pointer(arg_skip)) {
-                               type_t *const exp_to = skip_typeref(expected_type->pointer.points_to);
-                               type_t *const arg_to = skip_typeref(arg_skip->pointer.points_to);
-                               if (arg_to == exp_to) {
+               {       /* create a scope here to prevent warning about the jump to next_arg */
+                       type_t *const arg_type = arg->expression->base.type;
+                       if (is_type_pointer(expected_type)) {
+                               type_t *const arg_skip = skip_typeref(arg_type);
+                               if (is_type_pointer(arg_skip)) {
+                                       type_t *const exp_to = skip_typeref(expected_type->pointer.points_to);
+                                       type_t *const arg_to = skip_typeref(arg_skip->pointer.points_to);
+                                       if ((arg_to->base.qualifiers & ~expected_qual) == 0 &&
+                                               get_unqualified_type(arg_to) == exp_to) {
+                                               goto next_arg;
+                                       }
+                               }
+                       } else {
+                               if (get_unqualified_type(skip_typeref(arg_type)) == expected_type) {
                                        goto next_arg;
                                }
                        }
-               } else {
-                       if (get_unqualified_type(skip_typeref(arg_type)) == expected_type) {
-                               goto next_arg;
+                       if (is_type_valid(arg_type)) {
+                               warningf(pos,
+                                       "argument type '%T' does not match conversion specifier '%%%s%c'",
+                                       arg_type, get_length_modifier_name(fmt_mod), (char)*fmt);
                        }
                }
-               if (is_type_valid(arg_type)) {
-                       warningf(pos,
-                               "argument type '%T' does not match conversion specifier '%%%s%c'",
-                               arg_type, get_length_modifier_name(fmt_mod), (char)*fmt);
-               }
-
 next_arg:
                arg = arg->next;
        }