[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/cppcheck-opensource/cppcheck/main/test/testio.cpp [Back]  [Original]

/*
 * Cppcheck - A tool for static C/C++ code analysis
 * Copyright (C) 2007-2026 Cppcheck team.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */

#include "checkio.h"
#include "errortypes.h"
#include "fixture.h"
#include "helpers.h"
#include "platform.h"
#include "settings.h"

#include 
#include 

class TestIO : public TestFixture {
public:
    TestIO() : TestFixture("TestIO") {}

private:
    const Settings settings = settingsBuilder().library("std.cfg").library("windows.cfg").library("qt.cfg").build();
    /*const*/ Settings settings1 = settingsBuilder().library("std.cfg").library("windows.cfg").library("qt.cfg").severity(Severity::warning).severity(Severity::style).build();

    void run() override {
        mNewTemplate = true;
        TEST_CASE(coutCerrMisusage);

        TEST_CASE(wrongMode_simple);
        TEST_CASE(wrongMode_complex);
        TEST_CASE(useClosedFile);
        TEST_CASE(fileIOwithoutPositioning);
        TEST_CASE(seekOnAppendedFile);
        TEST_CASE(fflushOnInputStream);
        TEST_CASE(ftellCompatibility);
        TEST_CASE(incompatibleFileOpen);
        TEST_CASE(testWrongfeofUsage); // #958

        TEST_CASE(testScanf1); // Scanf without field limiters
        TEST_CASE(testScanf2);
        TEST_CASE(testScanf3); // #3494
        TEST_CASE(testScanf4); // #ticket 2553
        TEST_CASE(testScanf5); // #10632
        TEST_CASE(testScanf6);

        mNewTemplate = false;
        TEST_CASE(testScanfArgument);
        TEST_CASE(testPrintfArgument);
        TEST_CASE(testPrintfArgumentVariables);
        mNewTemplate = true;
        TEST_CASE(testPosixPrintfScanfParameterPosition);  // #4900

        TEST_CASE(testMicrosoftPrintfArgument); // ticket #4902
        TEST_CASE(testMicrosoftScanfArgument);
        TEST_CASE(testMicrosoftCStringFormatArguments); // ticket #4920
        TEST_CASE(testMicrosoftSecurePrintfArgument);
        TEST_CASE(testMicrosoftSecureScanfArgument);

        TEST_CASE(testQStringFormatArguments);

        TEST_CASE(testTernary); // ticket #6182
        TEST_CASE(testUnsignedConst); // ticket #6132

        TEST_CASE(testAstType); // #7014
        TEST_CASE(testPrintf0WithSuffix); // ticket #7069
        TEST_CASE(testReturnValueTypeStdLib);

        TEST_CASE(testPrintfTypeAlias1);
        TEST_CASE(testPrintfAuto); // #8992
        TEST_CASE(testPrintfParenthesis); // #8489
        TEST_CASE(testStdDistance); // #10304
        TEST_CASE(testParameterPack); // #11289

        TEST_CASE(testDefaultSignInt); // #13363
        TEST_CASE(testPrintfWithGeneric); // #13592
    }

    struct CheckOptions
    {
        bool inconclusive = false;
        bool portability = false;
        Platform::Type platform = Platform::Type::Unspecified;
        char defaultSign = '\0';
        bool onlyFormatStr = false;
        bool cpp = true;
    };

#define check(...) check_(__FILE__, __LINE__, __VA_ARGS__)
    template
    void check_(const char* file, int line, const char (&code)[size], const CheckOptions& options = make_default_obj()) {
        // TODO: using dedicated Settings (i.e. copying it) object causes major slowdown
        settings1.severity.setEnabled(Severity::portability, options.portability);
        settings1.certainty.setEnabled(Certainty::inconclusive, options.inconclusive);
        PLATFORM(settings1.platform, options.platform);
        settings1.platform.defaultSign = options.defaultSign;

        // Tokenize..
        SimpleTokenizer tokenizer(settings1, *this, options.cpp);
        ASSERT_LOC(tokenizer.tokenize(code), file, line);

        // Check..
        if (options.onlyFormatStr) {
            CheckIOImpl checkIO(&tokenizer, settings1, *this);
            checkIO.checkWrongPrintfScanfArguments();
            return;
        }
        CheckIO check;
        runChecks(check, tokenizer, *this);
    }

    void coutCerrMisusage() {
        check(
            "void foo() {\n"
            "  std::cout d, foo->bar[0].i, a[0],\n"
              "        f[0].d, f[0].baz.i, f[0].bar[0].i);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:13]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'double'.\n"
                      "[test.cpp:13]: (warning) %f in format string (no. 2) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:13]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'int'.\n"
                      "[test.cpp:13]: (warning) %d in format string (no. 4) requires 'int' but the argument type is 'double'.\n"
                      "[test.cpp:13]: (warning) %f in format string (no. 5) requires 'double' but the argument type is 'int'.\n"
                      "[test.cpp:13]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'int'.\n", errout_str());

        check("short f() { return 0; }\n"
              "void foo() { printf(\"%d %u %lu %I64u %I64d %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 4) requires 'unsigned __int64' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 5) requires '__int64' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'signed short'.\n", errout_str());

        check("unsigned short f() { return 0; }\n"
              "void foo() { printf(\"%u %d %ld %I64d %I64u %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 4) requires '__int64' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 5) requires 'unsigned __int64' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned short'.\n", errout_str());

        check("int f() { return 0; }\n"
              "void foo() { printf(\"%d %u %lu %I64u %I64d %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 4) requires 'unsigned __int64' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 5) requires '__int64' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("unsigned int f() { return 0; }\n"
              "void foo() { printf(\"%u %d %ld %I64d %I64u %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 4) requires '__int64' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 5) requires 'unsigned __int64' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned int'.\n", errout_str());

        check("long f() { return 0; }\n"
              "void foo() { printf(\"%ld %u %lu %I64u %I64d %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 4) requires 'unsigned __int64' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 5) requires '__int64' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'signed long'.\n", errout_str());

        check("unsigned long f() { return 0; }\n"
              "void foo() { printf(\"%lu %d %ld %I64d %I64u %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 4) requires '__int64' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 5) requires 'unsigned __int64' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned long'.\n", errout_str());

        check("long long f() { return 0; }\n"
              "void foo() { printf(\"%lld %u %lu %I64u %I64d %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed long long'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed long long'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 4) requires 'unsigned __int64' but the argument type is 'signed long long'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'signed long long'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'signed long long'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'signed long long'.\n", errout_str());

        check("unsigned long long f() { return 0; }\n"
              "void foo() { printf(\"%llu %d %ld %I64d %I64u %f %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned long long'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'unsigned long long'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 4) requires '__int64' but the argument type is 'unsigned long long'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 6) requires 'double' but the argument type is 'unsigned long long'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 7) requires 'long double' but the argument type is 'unsigned long long'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 8) requires an address but the argument type is 'unsigned long long'.\n", errout_str());

        check("float f() { return 0; }\n"
              "void foo() { printf(\"%f %d %ld %u %lu %I64d %I64u %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'float'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'float'.\n"
                      "[test.cpp:2]: (warning) %u in format string (no. 4) requires 'unsigned int' but the argument type is 'float'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 5) requires 'unsigned long' but the argument type is 'float'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 6) requires '__int64' but the argument type is 'float'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 7) requires 'unsigned __int64' but the argument type is 'float'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 8) requires 'long double' but the argument type is 'float'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 9) requires an address but the argument type is 'float'.\n", errout_str());

        check("double f() { return 0; }\n"
              "void foo() { printf(\"%f %d %ld %u %lu %I64d %I64u %Lf %p\", f(), f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'double'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'double'.\n"
                      "[test.cpp:2]: (warning) %u in format string (no. 4) requires 'unsigned int' but the argument type is 'double'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 5) requires 'unsigned long' but the argument type is 'double'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 6) requires '__int64' but the argument type is 'double'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 7) requires 'unsigned __int64' but the argument type is 'double'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 8) requires 'long double' but the argument type is 'double'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 9) requires an address but the argument type is 'double'.\n", errout_str());

        check("long double f() { return 0; }\n"
              "void foo() { printf(\"%Lf %d %ld %u %lu %I64d %I64u %f %p\", f(), f(), f(), f(), f(), f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'long double'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'long double'.\n"
                      "[test.cpp:2]: (warning) %u in format string (no. 4) requires 'unsigned int' but the argument type is 'long double'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 5) requires 'unsigned long' but the argument type is 'long double'.\n"
                      "[test.cpp:2]: (warning) %I64d in format string (no. 6) requires '__int64' but the argument type is 'long double'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 7) requires 'unsigned __int64' but the argument type is 'long double'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 8) requires 'double' but the argument type is 'long double'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 9) requires an address but the argument type is 'long double'.\n", errout_str());

        check("int f() { return 0; }\n"
              "void foo() { printf(\"%I64d %I64u %I64x %d\", f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %I64d in format string (no. 1) requires '__int64' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %I64u in format string (no. 2) requires 'unsigned __int64' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %I64x in format string (no. 3) requires 'unsigned __int64' but the argument type is 'signed int'.\n", errout_str());

        check("long long f() { return 0; }\n"
              "void foo() { printf(\"%I32d %I32u %I32x %lld\", f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %I32d in format string (no. 1) requires '__int32' but the argument type is 'signed long long'.\n"
                      "[test.cpp:2]: (warning) %I32u in format string (no. 2) requires 'unsigned __int32' but the argument type is 'signed long long'.\n"
                      "[test.cpp:2]: (warning) %I32x in format string (no. 3) requires 'unsigned __int32' but the argument type is 'signed long long'.\n", errout_str());

        check("unsigned long long f() { return 0; }\n"
              "void foo() { printf(\"%I32d %I32u %I32x %llx\", f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned long long'.\n"
                      "[test.cpp:2]: (warning) %I32u in format string (no. 2) requires 'unsigned __int32' but the argument type is 'unsigned long long'.\n"
                      "[test.cpp:2]: (warning) %I32x in format string (no. 3) requires 'unsigned __int32' but the argument type is 'unsigned long long'.\n", errout_str());

        check("signed char f() { return 0; }\n"
              "void foo() { printf(\"%Id %Iu %Ix %hhi\", f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %Id in format string (no. 1) requires 'ptrdiff_t' but the argument type is 'signed char'.\n"
                      "[test.cpp:2]: (warning) %Iu in format string (no. 2) requires 'size_t' but the argument type is 'signed char'.\n"
                      "[test.cpp:2]: (warning) %Ix in format string (no. 3) requires 'size_t' but the argument type is 'signed char'.\n", errout_str());

        check("unsigned char f() { return 0; }\n"
              "void foo() { printf(\"%Id %Iu %Ix %hho\", f(), f(), f(), f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %Id in format string (no. 1) requires 'ptrdiff_t' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:2]: (warning) %Iu in format string (no. 2) requires 'size_t' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:2]: (warning) %Ix in format string (no. 3) requires 'size_t' but the argument type is 'unsigned char'.\n", errout_str());

        check("namespace bar { int f() { return 0; } }\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", bar::f(), bar::f(), bar::f(), bar::f(), bar::f(), bar::f()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int i; } f;\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", f.i, f.i, f.i, f.i, f.i, f.i); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { unsigned int u; } f;\n"
              "void foo() { printf(\"%u %d %ld %f %Lf %p\", f.u, f.u, f.u, f.u, f.u, f.u); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'unsigned int'.\n", errout_str());

        check("struct Fred { unsigned int ui() { return 0; } } f;\n"
              "void foo() { printf(\"%u %d %ld %f %Lf %p\", f.ui(), f.ui(), f.ui(), f.ui(), f.ui(), f.ui()); }");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %p in format string (no. 6) requires an address but the argument type is 'unsigned int'.\n", errout_str());

        // #4975
        check("void f(int len, int newline) {\n"
              "    printf(\"%s\", newline ? a : str + len);\n"
              "    printf(\"%s\", newline + newline);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %s in format string (no. 1) requires 'char *' but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int i; } f;\n"
              "struct Fred & bar() { };\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int i; } f;\n"
              "const struct Fred & bar() { };\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int i; } f;\n"
              "static const struct Fred & bar() { };\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int i; } f[2];\n"
              "struct Fred * bar() { return f; };\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i); }");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int i; } f[2];\n"
              "const struct Fred * bar() { return f; };\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i); }");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int i; } f[2];\n"
              "static const struct Fred * bar() { return f; };\n"
              "void foo() { printf(\"%d %u %lu %f %Lf %p\", bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i, bar()[0].i); }");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %lu in format string (no. 3) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %Lf in format string (no. 5) requires 'long double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %p in format string (no. 6) requires an address but the argument type is 'signed int'.\n", errout_str());

        check("struct Fred { int32_t i; } f;\n"
              "struct Fred & bar() { };\n"
              "void foo() { printf(\"%d %ld %u %lu %f %Lf\", bar().i, bar().i, bar().i, bar().i, bar().i, bar().i); }");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %ld in format string (no. 2) requires 'long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %u in format string (no. 3) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %lu in format string (no. 4) requires 'unsigned long' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 5) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %Lf in format string (no. 6) requires 'long double' but the argument type is 'signed int'.\n",
                      errout_str());

        // #4984
        check("void f(double *x) {\n"
              "    printf(\"%f\", x[0]);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("int array[10];\n"
              "int * foo() { return array; }\n"
              "void f() {\n"
              "    printf(\"%f\", foo()[0]);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:4]: (warning) %f in format string (no. 1) requires 'double' but the argument type is 'signed int'.\n", errout_str());

        check("struct Base { int length() { } };\n"
              "struct Derived : public Base { };\n"
              "void foo(Derived * d) {\n"
              "    printf(\"%f\", d.length());\n"
              "}");
        ASSERT_EQUALS("[test.cpp:4]: (warning) %f in format string (no. 1) requires 'double' but the argument type is 'signed int'.\n", errout_str());

        check("std::vector v;\n"
              "void foo() {\n"
              "    printf(\"%d %u %f\", v[0], v[0], v[0]);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'signed int'.\n", errout_str());

        // #4999 (crash)
        check("int bar(int a);\n"
              "void foo() {\n"
              "    printf(\"%d\", bar(0));\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("std::vector v;\n"
              "std::string s;\n"
              "void foo() {\n"
              "    printf(\"%zu %Iu %d %f\", v.size(), v.size(), v.size(), v.size());\n"
              "    printf(\"%zu %Iu %d %f\", s.size(), s.size(), s.size(), s.size());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:4]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long}'.\n", errout_str());

        check("std::vector v;\n"
              "std::string s;\n"
              "void foo() {\n"
              "    printf(\"%zu %Iu %d %f\", v.size(), v.size(), v.size(), v.size());\n"
              "    printf(\"%zu %Iu %d %f\", s.size(), s.size(), s.size(), s.size());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:4]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long long}'.\n"
                      "[test.cpp:4]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long long}'.\n"
                      "[test.cpp:5]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long long}'.\n"
                      "[test.cpp:5]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long long}'.\n", errout_str());

        check("std::vector v;\n"
              "std::string s;\n"
              "void foo() {\n"
              "    printf(\"%zu %Iu %d %f\", v.size(), v.size(), v.size(), v.size());\n"
              "    printf(\"%zu %Iu %d %f\", s.size(), s.size(), s.size(), s.size());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix32));
        ASSERT_EQUALS("[test.cpp:4]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:4]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long}'.\n", errout_str());

        check("std::vector v;\n"
              "std::string s;\n"
              "void foo() {\n"
              "    printf(\"%zu %Iu %d %f\", v.size(), v.size(), v.size(), v.size());\n"
              "    printf(\"%zu %Iu %d %f\", s.size(), s.size(), s.size(), s.size());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:4]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:4]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long}'.\n", errout_str());

        check("class Fred : public std::vector {} v;\n"
              "std::string s;\n"
              "void foo() {\n"
              "    printf(\"%zu %Iu %d %f\", v.size(), v.size(), v.size(), v.size());\n"
              "    printf(\"%zu %Iu %d %f\", s.size(), s.size(), s.size(), s.size());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:4]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:4]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %d in format string (no. 3) requires 'int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:5]: (portability) %f in format string (no. 4) requires 'double' but the argument type is 'std::size_t {aka unsigned long}'.\n", errout_str());

        check("class Fred : public std::vector {} v;\n"
              "void foo() {\n"
              "    printf(\"%d %u %f\", v[0], v[0], v[0]);\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'int'.\n", errout_str());

        check("std::string s;\n"
              "void foo() {\n"
              "    printf(\"%s %p %u %d %f\", s.c_str(), s.c_str(), s.c_str(), s.c_str(), s.c_str());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 3) requires 'unsigned int' but the argument type is 'const char *'.\n"
                      "[test.cpp:3]: (warning) %d in format string (no. 4) requires 'int' but the argument type is 'const char *'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 5) requires 'double' but the argument type is 'const char *'.\n", errout_str());

        check("std::vector array;\n"
              "char * p = 0;\n"
              "char q[] = \"abc\";\n"
              "char r[10] = { 0 };\n"
              "size_t s;\n"
              "void foo() {\n"
              "    printf(\"%zu %zu\", array.size(), s);\n"
              "    printf(\"%u %u %u\", p, q, r);\n"
              "    printf(\"%u %u\", array.size(), s);\n"
              "    printf(\"%lu %lu\", array.size(), s);\n"
              "    printf(\"%llu %llu\", array.size(), s);\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:8]: (warning) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'char *'.\n"
                      "[test.cpp:8]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'char *'.\n"
                      "[test.cpp:8]: (warning) %u in format string (no. 3) requires 'unsigned int' but the argument type is 'char *'.\n"
                      "[test.cpp:9]: (portability) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:9]: (portability) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:10]: (portability) %lu in format string (no. 1) requires 'unsigned long' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:10]: (portability) %lu in format string (no. 2) requires 'unsigned long' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:11]: (portability) %llu in format string (no. 1) requires 'unsigned long long' but the argument type is 'std::size_t {aka unsigned long}'.\n"
                      "[test.cpp:11]: (portability) %llu in format string (no. 2) requires 'unsigned long long' but the argument type is 'size_t {aka unsigned long}'.\n", errout_str());

        check("bool b; bool bf();\n"
              "char c; char cf();\n"
              "signed char sc; signed char scf();\n"
              "unsigned char uc; unsigned char ucf();\n"
              "short s; short sf();\n"
              "unsigned short us; unsigned short usf();\n"
              "size_t st; size_t stf();\n"
              "ptrdiff_t pt; ptrdiff_t ptf();\n"
              "char * pc; char * pcf();\n"
              "char cl[] = \"123\";\n"
              "char ca[3];\n"
              "void foo() {\n"
              "    printf(\"%td %zd %d %d %d %d %d %d %d %d %d %d %d\", pt, pt, b, c, sc, uc, s, us, st, pt, pc, cl, ca);\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:13]: (portability) %zd in format string (no. 2) requires 'ssize_t' but the argument type is 'ptrdiff_t {aka signed long}'.\n"
                      "[test.cpp:13]: (portability) %d in format string (no. 9) requires 'int' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:13]: (portability) %d in format string (no. 10) requires 'int' but the argument type is 'ptrdiff_t {aka signed long}'.\n"
                      "[test.cpp:13]: (warning) %d in format string (no. 11) requires 'int' but the argument type is 'char *'.\n"
                      "[test.cpp:13]: (warning) %d in format string (no. 12) requires 'int' but the argument type is 'char *'.\n"
                      "[test.cpp:13]: (warning) %d in format string (no. 13) requires 'int' but the argument type is 'char *'.\n", errout_str());

        check("bool b; bool bf();\n"
              "char c; char cf();\n"
              "signed char sc; signed char scf();\n"
              "unsigned char uc; unsigned char ucf();\n"
              "short s; short sf();\n"
              "unsigned short us; unsigned short usf();\n"
              "size_t st; size_t stf();\n"
              "ptrdiff_t pt; ptrdiff_t ptf();\n"
              "char * pc; char * pcf();\n"
              "char cl[] = \"123\";\n"
              "char ca[3];\n"
              "void foo() {\n"
              "    printf(\"%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\", b, c, sc, uc, s, us, st, pt, pc, cl, ca);\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:13]: (warning) %ld in format string (no. 1) requires 'long' but the argument type is 'bool'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 2) requires 'long' but the argument type is 'char'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'signed char'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 4) requires 'long' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 5) requires 'long' but the argument type is 'signed short'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 6) requires 'long' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:13]: (portability) %ld in format string (no. 7) requires 'long' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:13]: (portability) %ld in format string (no. 8) requires 'long' but the argument type is 'ptrdiff_t {aka signed long}'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 9) requires 'long' but the argument type is 'char *'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 10) requires 'long' but the argument type is 'char *'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 11) requires 'long' but the argument type is 'char *'.\n", errout_str());


        check("bool b; bool bf();\n"
              "char c; char cf();\n"
              "signed char sc; signed char scf();\n"
              "unsigned char uc; unsigned char ucf();\n"
              "short s; short sf();\n"
              "unsigned short us; unsigned short usf();\n"
              "size_t st; size_t stf();\n"
              "ptrdiff_t pt; ptrdiff_t ptf();\n"
              "char * pc; char * pcf();\n"
              "char cl[] = \"123\";\n"
              "char ca[3];\n"
              "void foo() {\n"
              "    printf(\"%td %zd %d %d %d %d %d %d %d %d %d\", ptf(), ptf(), bf(), cf(), scf(), ucf(), sf(), usf(), stf(), ptf(), pcf());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:13]: (portability) %zd in format string (no. 2) requires 'ssize_t' but the argument type is 'ptrdiff_t {aka signed long}'.\n"
                      "[test.cpp:13]: (portability) %d in format string (no. 9) requires 'int' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:13]: (portability) %d in format string (no. 10) requires 'int' but the argument type is 'ptrdiff_t {aka signed long}'.\n"
                      "[test.cpp:13]: (warning) %d in format string (no. 11) requires 'int' but the argument type is 'char *'.\n", errout_str());

        check("bool b; bool bf();\n"
              "char c; char cf();\n"
              "signed char sc; signed char scf();\n"
              "unsigned char uc; unsigned char ucf();\n"
              "short s; short sf();\n"
              "unsigned short us; unsigned short usf();\n"
              "size_t st; size_t stf();\n"
              "ptrdiff_t pt; ptrdiff_t ptf();\n"
              "char * pc; char * pcf();\n"
              "char cl[] = \"123\";\n"
              "char ca[3];\n"
              "void foo() {\n"
              "    printf(\"%ld %ld %ld %ld %ld %ld %ld %ld %ld\", bf(), cf(), scf(), ucf(), sf(), usf(), stf(), ptf(), pcf());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:13]: (warning) %ld in format string (no. 1) requires 'long' but the argument type is 'bool'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 2) requires 'long' but the argument type is 'char'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 3) requires 'long' but the argument type is 'signed char'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 4) requires 'long' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 5) requires 'long' but the argument type is 'signed short'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 6) requires 'long' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:13]: (portability) %ld in format string (no. 7) requires 'long' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:13]: (portability) %ld in format string (no. 8) requires 'long' but the argument type is 'ptrdiff_t {aka signed long}'.\n"
                      "[test.cpp:13]: (warning) %ld in format string (no. 9) requires 'long' but the argument type is 'char *'.\n", errout_str());

        check("struct A {};\n"
              "class B : public std::vector {} b;\n"
              "class C : public std::vector {} c;\n"
              "std::string s;\n"
              "void foo() {\n"
              "    printf(\"%zu %u\", b.size(), b.size());\n"
              "    printf(\"%p %d\", b[0], b[0]);\n"
              "    printf(\"%p %d\", c[0], c[0]);\n"
              "    printf(\"%p %d\", s.c_str(), s.c_str());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:6]: (portability) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'size_t {aka unsigned long}'.\n"
                      "[test.cpp:7]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'const int *'.\n"
                      "[test.cpp:8]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'const struct A *'.\n"
                      "[test.cpp:9]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'const char *'.\n", errout_str());

        check("class A : public std::vector {} a;\n"
              "class B : public std::string {} b;\n"
              "std::string s;\n"
              "void foo() {\n"
              "    printf(\"%p %d\", a[0].c_str(), a[0].c_str());\n"
              "    printf(\"%c %p\", b[0], b[0]);\n"
              "    printf(\"%c %p\", s[0], s[0]);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:5]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'const char *'.\n"
                      "[test.cpp:6]: (warning) %p in format string (no. 2) requires an address but the argument type is 'char'.\n"
                      "[test.cpp:7]: (warning) %p in format string (no. 2) requires an address but the argument type is 'char'.\n", errout_str());

        check("template \n"
              "struct buffer {\n"
              "    size_t size();\n"
              "};\n"
              "buffer b;\n"
              "void foo() {\n"
              "    printf(\"%u\", b.size());\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:7]: (portability) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'size_t {aka unsigned long}'.\n", errout_str());

        check("DWORD a;\n"
              "DWORD_PTR b;\n"
              "void foo() {\n"
              "    printf(\"%u %u\", a, b);\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4]: (portability) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'DWORD {aka unsigned long}'.\n"
                      "[test.cpp:4]: (portability) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'DWORD_PTR {aka unsigned long}'.\n", errout_str());

        check("unsigned long a[] = { 1, 2 };\n"
              "void foo() {\n"
              "    printf(\"%d %d %x \", a[0], a[0], a[0]);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:3]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:3]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'unsigned long'.\n"
                      "[test.cpp:3]: (warning) %x in format string (no. 3) requires 'unsigned int' but the argument type is 'unsigned long'.\n", errout_str());

        check("void foo (wchar_t c) {\n" // ticket #5051 false positive
              "    printf(\"%c\", c);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "    printf(\"%f %d\", static_cast(1.0f), reinterpret_cast(0));\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %f in format string (no. 1) requires 'double' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'const void *'.\n", errout_str());

        check("void foo() {\n"
              "    UNKNOWN * u;\n"
              "    printf(\"%d %x %u %f\", u[i], u[i], u[i], u[i]);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "    long * l;\n"
              "    printf(\"%d %x %u %f\", l[i], l[i], l[i], l[i]);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'signed long'.\n"
                      "[test.cpp:3]: (warning) %x in format string (no. 2) requires 'unsigned int' but the argument type is 'signed long'.\n"
                      "[test.cpp:3]: (warning) %u in format string (no. 3) requires 'unsigned int' but the argument type is 'signed long'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 4) requires 'double' but the argument type is 'signed long'.\n", errout_str());

        check("void f() {\n" // #5104
              "    myvector v1(1,0);\n"
              "    printf(\"%d\",v1[0]);\n"
              "    myvector v2(1,0);\n"
              "    printf(\"%d\",v2[0]);\n"
              "    myvector v3(1,0);\n"
              "    printf(\"%u\",v3[0]);\n"
              "    myvector v4(1,0);\n"
              "    printf(\"%x\",v4[0]);\n"
              "    myvector v5(1,0);\n"
              "    printf(\"%f\",v5[0]);\n"
              "    myvector v6(1,0);\n"
              "    printf(\"%u\",v6[0]);\n"
              "    myvector v7(1,0);\n"
              "    printf(\"%s\",v7[0]);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("std::vector v;\n" // #5151
              "void foo() {\n"
              "   printf(\"%c %u %f\", v.at(32), v.at(32), v.at(32));\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'char'.\n"
                      "[test.cpp:3]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'char'.\n", errout_str());

        // #5195 (segmentation fault)
        check("void T::a(const std::vector& vx) {\n"
              "    printf(\"%f\", vx.at(0));\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        // #5486
        check("void foo() {\n"
              "    ssize_t test = 0;\n"
              "    printf(\"%zd\", test);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        // #6009
        check("extern std::string StringByReturnValue();\n"
              "extern int         IntByReturnValue();\n"
              "void MyFunction() {\n"
              "    printf( \"%s - %s\", StringByReturnValue(), IntByReturnValue() );\n"
              "}");
        ASSERT_EQUALS("[test.cpp:4]: (warning) %s in format string (no. 1) requires 'char *' but the argument type is 'std::string'.\n"
                      "[test.cpp:4]: (warning) %s in format string (no. 2) requires 'char *' but the argument type is 'signed int'.\n", errout_str());

        check("template \n"
              "struct Array {\n"
              "    T data[S];\n"
              "    T & operator [] (size_t i) { return data[i]; }\n"
              "};\n"
              "void foo() {\n"
              "    Array array1;\n"
              "    Array array2;\n"
              "    printf(\"%u %u\", array1[0], array2[0]);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:9]: (warning) %u in format string (no. 1) requires 'unsigned int' but the argument type is 'int'.\n"
                      "[test.cpp:9]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'float'.\n", errout_str());

        // Ticket #7445
        check("struct S { unsigned short x; } s = {0};\n"
              "void foo() {\n"
              "    printf(\"%d\", s.x);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        // Ticket #7601
        check("void foo(int i, unsigned int ui, long long ll, unsigned long long ull) {\n"
              "    printf(\"%Ld %Lu %Ld %Lu\", i, ui, ll, ull);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %Ld in format string (no. 1) requires 'long long' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %Lu in format string (no. 2) requires 'unsigned long long' but the argument type is 'unsigned int'.\n", errout_str());

        check("void foo(char c, unsigned char uc, short s, unsigned short us, int i, unsigned int ui, long l, unsigned long ul) {\n"
              "    printf(\"%hhd %hhd %hhd %hhd %hhd %hhd %hhd %hhd\", c, uc, s, us, i, ui, l, ul);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %hhd in format string (no. 2) requires 'char' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:2]: (warning) %hhd in format string (no. 3) requires 'char' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %hhd in format string (no. 4) requires 'char' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %hhd in format string (no. 5) requires 'char' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %hhd in format string (no. 6) requires 'char' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %hhd in format string (no. 7) requires 'char' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %hhd in format string (no. 8) requires 'char' but the argument type is 'unsigned long'.\n", errout_str());

        check("void foo(char c, unsigned char uc, short s, unsigned short us, int i, unsigned int ui, long l, unsigned long ul) {\n"
              "    printf(\"%hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu\", c, uc, s, us, i, ui, l, ul);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %hhu in format string (no. 1) requires 'unsigned char' but the argument type is 'char'.\n"
                      "[test.cpp:2]: (warning) %hhu in format string (no. 3) requires 'unsigned char' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %hhu in format string (no. 4) requires 'unsigned char' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %hhu in format string (no. 5) requires 'unsigned char' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %hhu in format string (no. 6) requires 'unsigned char' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %hhu in format string (no. 7) requires 'unsigned char' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %hhu in format string (no. 8) requires 'unsigned char' but the argument type is 'unsigned long'.\n", errout_str());

        check("void foo(char c, unsigned char uc, short s, unsigned short us, int i, unsigned int ui, long l, unsigned long ul) {\n"
              "    printf(\"%hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx\", c, uc, s, us, i, ui, l, ul);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %hhx in format string (no. 1) requires 'unsigned char' but the argument type is 'char'.\n"
                      "[test.cpp:2]: (warning) %hhx in format string (no. 3) requires 'unsigned char' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %hhx in format string (no. 4) requires 'unsigned char' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %hhx in format string (no. 5) requires 'unsigned char' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %hhx in format string (no. 6) requires 'unsigned char' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %hhx in format string (no. 7) requires 'unsigned char' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %hhx in format string (no. 8) requires 'unsigned char' but the argument type is 'unsigned long'.\n", errout_str());

        check("void foo(char c, unsigned char uc, short s, unsigned short us, int i, unsigned int ui, long l, unsigned long ul) {\n"
              "    printf(\"%hd %hd %hd %hd %hd %hd %hd %hd\", c, uc, s, us, i, ui, l, ul);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %hd in format string (no. 1) requires 'short' but the argument type is 'char'.\n"
                      "[test.cpp:2]: (warning) %hd in format string (no. 2) requires 'short' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:2]: (warning) %hd in format string (no. 4) requires 'short' but the argument type is 'unsigned short'.\n"
                      "[test.cpp:2]: (warning) %hd in format string (no. 5) requires 'short' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %hd in format string (no. 6) requires 'short' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %hd in format string (no. 7) requires 'short' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %hd in format string (no. 8) requires 'short' but the argument type is 'unsigned long'.\n", errout_str());

        check("void foo(char c, unsigned char uc, short s, unsigned short us, int i, unsigned int ui, long l, unsigned long ul) {\n"
              "    printf(\"%hu %hu %hu %hu %hu %hu %hu %hu\", c, uc, s, us, i, ui, l, ul);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %hu in format string (no. 1) requires 'unsigned short' but the argument type is 'char'.\n"
                      "[test.cpp:2]: (warning) %hu in format string (no. 2) requires 'unsigned short' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:2]: (warning) %hu in format string (no. 3) requires 'unsigned short' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %hu in format string (no. 5) requires 'unsigned short' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %hu in format string (no. 6) requires 'unsigned short' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %hu in format string (no. 7) requires 'unsigned short' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %hu in format string (no. 8) requires 'unsigned short' but the argument type is 'unsigned long'.\n", errout_str());

        check("void foo(char c, unsigned char uc, short s, unsigned short us, int i, unsigned int ui, long l, unsigned long ul) {\n"
              "    printf(\"%hx %hx %hx %hx %hx %hx %hx %hx\", c, uc, s, us, i, ui, l, ul);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2]: (warning) %hx in format string (no. 1) requires 'unsigned short' but the argument type is 'char'.\n"
                      "[test.cpp:2]: (warning) %hx in format string (no. 2) requires 'unsigned short' but the argument type is 'unsigned char'.\n"
                      "[test.cpp:2]: (warning) %hx in format string (no. 3) requires 'unsigned short' but the argument type is 'signed short'.\n"
                      "[test.cpp:2]: (warning) %hx in format string (no. 5) requires 'unsigned short' but the argument type is 'signed int'.\n"
                      "[test.cpp:2]: (warning) %hx in format string (no. 6) requires 'unsigned short' but the argument type is 'unsigned int'.\n"
                      "[test.cpp:2]: (warning) %hx in format string (no. 7) requires 'unsigned short' but the argument type is 'signed long'.\n"
                      "[test.cpp:2]: (warning) %hx in format string (no. 8) requires 'unsigned short' but the argument type is 'unsigned long'.\n", errout_str());

        // #7837 - Use ValueType for function call
        check("struct S {\n"
              "  double (* f)(double);\n"
              "};\n"
              "\n"
              "void foo(struct S x) {\n"
              "  printf(\"%f\", x.f(4.0));\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("enum E : uint8_t { E0 }; \n" // #7959
              "void f(E e) {\n"
              "    printf(\"%hhu\", e);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("enum E : uint8_t { E0 }; \n"
              "void f(E e) {\n"
              "    printf(\"%lu\", e);\n"
              "}");
        TODO_ASSERT_EQUALS("[test.cpp:3]: (warning) %lu in format string (no. 1) requires 'unsigned long' but the argument type is 'uint8_t'.\n",
                           "",
                           errout_str());

        check("void f() {\n"
              "    printf(\"%lu\", sizeof(char));\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:2]: (portability) %lu in format string (no. 1) requires 'unsigned long' but the argument type is 'size_t {aka unsigned long long}'.\n",
                      errout_str());
    }

    void testPrintfArgumentVariables() {
        TEST_PRINTF_NOWARN("%u", "unsigned int", "bool");
        TEST_PRINTF_WARN("%u", "unsigned int", "char");
        TEST_PRINTF_WARN("%u", "unsigned int", "signed char");
        TEST_PRINTF_NOWARN("%u", "unsigned int", "unsigned char");
        TEST_PRINTF_WARN("%u", "unsigned int", "signed short");
        TEST_PRINTF_NOWARN("%u", "unsigned int", "unsigned short");
        TEST_PRINTF_WARN("%u", "unsigned int", "signed int");
        TEST_PRINTF_NOWARN("%u", "unsigned int", "unsigned int");
        TEST_PRINTF_WARN("%u", "unsigned int", "signed long");
        TEST_PRINTF_WARN("%u", "unsigned int", "unsigned long");
        TEST_PRINTF_WARN("%u", "unsigned int", "signed long long");
        TEST_PRINTF_WARN("%u", "unsigned int", "unsigned long long");
        TEST_PRINTF_WARN("%u", "unsigned int", "float");
        TEST_PRINTF_WARN("%u", "unsigned int", "double");
        TEST_PRINTF_WARN("%u", "unsigned int", "long double");
        TEST_PRINTF_WARN("%u", "unsigned int", "void *");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%u", "unsigned int", "uintptr_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%u", "unsigned int", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%u", "unsigned int", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%u", "unsigned int", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%u", "unsigned int", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%u", "unsigned int", "std::uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%u", "unsigned int", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%u", "unsigned int", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_NOWARN("%x", "unsigned int", "bool");
        //TODO TEST_PRINTF_WARN("%x", "unsigned int", "char");
        //TODO TEST_PRINTF_WARN("%x", "unsigned int", "signed char");
        TEST_PRINTF_NOWARN("%x", "unsigned int", "unsigned char");
        //TODO TEST_PRINTF_WARN("%x", "unsigned int", "signed short");
        TEST_PRINTF_NOWARN("%x", "unsigned int", "unsigned short");
        //TODO TEST_PRINTF_WARN("%x", "unsigned int", "signed int");
        TEST_PRINTF_NOWARN("%x", "unsigned int", "unsigned int");
        TEST_PRINTF_WARN("%x", "unsigned int", "signed long");
        TEST_PRINTF_WARN("%x", "unsigned int", "unsigned long");
        TEST_PRINTF_WARN("%x", "unsigned int", "signed long long");
        TEST_PRINTF_WARN("%x", "unsigned int", "unsigned long long");
        TEST_PRINTF_WARN("%x", "unsigned int", "float");
        TEST_PRINTF_WARN("%x", "unsigned int", "double");
        TEST_PRINTF_WARN("%x", "unsigned int", "long double");
        TEST_PRINTF_WARN("%x", "unsigned int", "void *");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%x", "unsigned int", "uintptr_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%x", "unsigned int", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%x", "unsigned int", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%x", "unsigned int", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%x", "unsigned int", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%x", "unsigned int", "std::uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%x", "unsigned int", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%x", "unsigned int", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%lu","unsigned long","bool");
        TEST_PRINTF_WARN("%lu","unsigned long","char");
        TEST_PRINTF_WARN("%lu","unsigned long","signed char");
        TEST_PRINTF_WARN("%lu","unsigned long","unsigned char");
        TEST_PRINTF_WARN("%lu","unsigned long","signed short");
        TEST_PRINTF_WARN("%lu","unsigned long","unsigned short");
        TEST_PRINTF_WARN("%lu","unsigned long","signed int");
        TEST_PRINTF_WARN("%lu","unsigned long","unsigned int");
        TEST_PRINTF_WARN("%lu","unsigned long","signed long");
        TEST_PRINTF_NOWARN("%lu","unsigned long","unsigned long");
        TEST_PRINTF_WARN("%lu","unsigned long","signed long long");
        TEST_PRINTF_WARN("%lu","unsigned long","unsigned long long");
        TEST_PRINTF_WARN("%lu","unsigned long","float");
        TEST_PRINTF_WARN("%lu","unsigned long","double");
        TEST_PRINTF_WARN("%lu","unsigned long","long double");
        TEST_PRINTF_WARN("%lu","unsigned long","void *");
        TEST_PRINTF_WARN_AKA("%lu","unsigned long","size_t","unsigned long","unsigned long long");
        TEST_PRINTF_WARN_AKA("%lu","unsigned long","ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%lu","unsigned long","ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lu","unsigned long","unsigned ptrdiff_t", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%lu","unsigned long","intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%lu","unsigned long","uintmax_t","unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%lu","unsigned long","intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lu","unsigned long","uintptr_t", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%lu","unsigned long","std::size_t","unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%lu","unsigned long","std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%lu","unsigned long","std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%lu","unsigned long","std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lu","unsigned long","std::uintmax_t", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%lu","unsigned long","std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lu","unsigned long","std::uintptr_t", "unsigned long long");

        TEST_PRINTF_WARN("%lx","unsigned long","bool");
        TEST_PRINTF_WARN("%lx","unsigned long","char");
        TEST_PRINTF_WARN("%lx","unsigned long","signed char");
        TEST_PRINTF_WARN("%lx","unsigned long","unsigned char");
        TEST_PRINTF_WARN("%lx","unsigned long","signed short");
        TEST_PRINTF_WARN("%lx","unsigned long","unsigned short");
        TEST_PRINTF_WARN("%lx","unsigned long","signed int");
        TEST_PRINTF_WARN("%lx","unsigned long","unsigned int");
        //TODO TEST_PRINTF_WARN("%lx","unsigned long","signed long");
        TEST_PRINTF_NOWARN("%lx","unsigned long","unsigned long");
        TEST_PRINTF_WARN("%lx","unsigned long","signed long long");
        TEST_PRINTF_WARN("%lx","unsigned long","unsigned long long");
        TEST_PRINTF_WARN("%lx","unsigned long","float");
        TEST_PRINTF_WARN("%lx","unsigned long","double");
        TEST_PRINTF_WARN("%lx","unsigned long","long double");
        TEST_PRINTF_WARN("%lx","unsigned long","void *");
        TEST_PRINTF_WARN_AKA("%lx","unsigned long","size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lx","unsigned long","ssize_t", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lx","unsigned long","ptrdiff_t", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lx","unsigned long","unsigned ptrdiff_t", "unsigned long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lx","unsigned long","intmax_t", "signed long long");
        TEST_PRINTF_WARN_AKA("%lx","unsigned long","uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lx","unsigned long","intptr_t", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN64("%lx","unsigned long","uintptr_t", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%lx","unsigned long","std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lx","unsigned long","std::ssize_t", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lx","unsigned long","std::ptrdiff_t", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lx","unsigned long","std::intmax_t", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lx","unsigned long","std::uintmax_t", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lx","unsigned long","std::intptr_t", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN64("%lx","unsigned long","std::uintptr_t", "unsigned long long");

        TEST_PRINTF_WARN("%llu","unsigned long long","bool");
        TEST_PRINTF_WARN("%llu","unsigned long long","char");
        TEST_PRINTF_WARN("%llu","unsigned long long","signed char");
        TEST_PRINTF_WARN("%llu","unsigned long long","unsigned char");
        TEST_PRINTF_WARN("%llu","unsigned long long","signed short");
        TEST_PRINTF_WARN("%llu","unsigned long long","unsigned short");
        TEST_PRINTF_WARN("%llu","unsigned long long","signed int");
        TEST_PRINTF_WARN("%llu","unsigned long long","unsigned int");
        TEST_PRINTF_WARN("%llu","unsigned long long","signed long");
        TEST_PRINTF_WARN("%llu","unsigned long long","unsigned long");
        TEST_PRINTF_WARN("%llu","unsigned long long","signed long long");
        TEST_PRINTF_NOWARN("%llu","unsigned long long","unsigned long long");
        TEST_PRINTF_WARN("%llu","unsigned long long","float");
        TEST_PRINTF_WARN("%llu","unsigned long long","double");
        TEST_PRINTF_WARN("%llu","unsigned long long","long double");
        TEST_PRINTF_WARN("%llu","unsigned long long","void *");
        TEST_PRINTF_WARN_AKA("%llu","unsigned long long","size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%llu","unsigned long long","ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%llu","unsigned long long","ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%llu","unsigned long long","unsigned ptrdiff_t", "unsigned long");
        TEST_PRINTF_WARN_AKA("%llu","unsigned long long","intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%llu","unsigned long long","uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%llu","unsigned long long","intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%llu","unsigned long long","uintptr_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP("%llu","unsigned long long","std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%llu","unsigned long long","std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%llu","unsigned long long","std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%llu","unsigned long long","std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llu","unsigned long long","std::uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP("%llu","unsigned long long","std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llu","unsigned long long","std::uintptr_t", "unsigned long");

        TEST_PRINTF_WARN("%llx","unsigned long long","bool");
        TEST_PRINTF_WARN("%llx","unsigned long long","char");
        TEST_PRINTF_WARN("%llx","unsigned long long","signed char");
        TEST_PRINTF_WARN("%llx","unsigned long long","unsigned char");
        TEST_PRINTF_WARN("%llx","unsigned long long","signed short");
        TEST_PRINTF_WARN("%llx","unsigned long long","unsigned short");
        TEST_PRINTF_WARN("%llx","unsigned long long","signed int");
        TEST_PRINTF_WARN("%llx","unsigned long long","unsigned int");
        TEST_PRINTF_WARN("%llx","unsigned long long","signed long");
        TEST_PRINTF_WARN("%llx","unsigned long long","unsigned long");
        //TODO TEST_PRINTF_WARN("%llx","unsigned long long","signed long long");
        TEST_PRINTF_NOWARN("%llx","unsigned long long","unsigned long long");
        TEST_PRINTF_WARN("%llx","unsigned long long","float");
        TEST_PRINTF_WARN("%llx","unsigned long long","double");
        TEST_PRINTF_WARN("%llx","unsigned long long","long double");
        TEST_PRINTF_WARN("%llx","unsigned long long","void *");
        TEST_PRINTF_WARN_AKA("%llx","unsigned long long","size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_WIN32("%llx","unsigned long long","ssize_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%llx","unsigned long long","ptrdiff_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%llx","unsigned long long","unsigned ptrdiff_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_WIN32("%llx","unsigned long long","intmax_t", "signed long");
        TEST_PRINTF_WARN_AKA("%llx","unsigned long long","uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_WIN32("%llx","unsigned long long","intptr_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%llx","unsigned long long","uintptr_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP("%llx","unsigned long long","std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llx","unsigned long long","std::ssize_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llx","unsigned long long","std::ptrdiff_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llx","unsigned long long","std::intmax_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llx","unsigned long long","std::uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llx","unsigned long long","std::intptr_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%llx","unsigned long long","std::uintptr_t", "unsigned long");

        TEST_PRINTF_WARN("%hu", "unsigned short", "bool");
        TEST_PRINTF_WARN("%hu", "unsigned short", "char");
        TEST_PRINTF_WARN("%hu", "unsigned short", "signed char");
        TEST_PRINTF_WARN("%hu", "unsigned short", "unsigned char");
        TEST_PRINTF_WARN("%hu", "unsigned short", "signed short");
        TEST_PRINTF_NOWARN("%hu", "unsigned short", "unsigned short");
        TEST_PRINTF_WARN("%hu", "unsigned short", "signed int");
        TEST_PRINTF_WARN("%hu", "unsigned short", "unsigned int");
        TEST_PRINTF_WARN("%hu", "unsigned short", "signed long");
        TEST_PRINTF_WARN("%hu", "unsigned short", "unsigned long");
        TEST_PRINTF_WARN("%hu", "unsigned short", "signed long long");
        TEST_PRINTF_WARN("%hu", "unsigned short", "unsigned long long");
        TEST_PRINTF_WARN("%hu", "unsigned short", "float");
        TEST_PRINTF_WARN("%hu", "unsigned short", "double");
        TEST_PRINTF_WARN("%hu", "unsigned short", "long double");
        TEST_PRINTF_WARN("%hu", "unsigned short", "void *");
        TEST_PRINTF_WARN_AKA("%hu", "unsigned short", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hu", "unsigned short", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hu", "unsigned short", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hu", "unsigned short", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hu", "unsigned short", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hu", "unsigned short", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hu", "unsigned short", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hu", "unsigned short", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hu", "unsigned short", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hu", "unsigned short", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hu", "unsigned short", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%hx", "unsigned short", "bool");
        TEST_PRINTF_WARN("%hx", "unsigned short", "char");
        TEST_PRINTF_WARN("%hx", "unsigned short", "signed char");
        TEST_PRINTF_WARN("%hx", "unsigned short", "unsigned char");
        TEST_PRINTF_WARN("%hx", "unsigned short", "signed short");
        TEST_PRINTF_NOWARN("%hx", "unsigned short", "unsigned short");
        TEST_PRINTF_WARN("%hx", "unsigned short", "signed int");
        TEST_PRINTF_WARN("%hx", "unsigned short", "unsigned int");
        TEST_PRINTF_WARN("%hx", "unsigned short", "signed long");
        TEST_PRINTF_WARN("%hx", "unsigned short", "unsigned long");
        TEST_PRINTF_WARN("%hx", "unsigned short", "signed long long");
        TEST_PRINTF_WARN("%hx", "unsigned short", "unsigned long long");
        TEST_PRINTF_WARN("%hx", "unsigned short", "float");
        TEST_PRINTF_WARN("%hx", "unsigned short", "double");
        TEST_PRINTF_WARN("%hx", "unsigned short", "long double");
        TEST_PRINTF_WARN("%hx", "unsigned short", "void *");
        TEST_PRINTF_WARN_AKA("%hx", "unsigned short", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hx", "unsigned short", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hx", "unsigned short", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hx", "unsigned short", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hx", "unsigned short", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hx", "unsigned short", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hx", "unsigned short", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hx", "unsigned short", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hx", "unsigned short", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hx", "unsigned short", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hx", "unsigned short", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%hhu", "unsigned char", "bool");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "char");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "signed char");
        TEST_PRINTF_NOWARN("%hhu", "unsigned char", "unsigned char");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "signed short");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "unsigned short");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "signed int");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "unsigned int");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "signed long");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "unsigned long");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "signed long long");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "unsigned long long");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "float");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "double");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "long double");
        TEST_PRINTF_WARN("%hhu", "unsigned char", "void *");
        TEST_PRINTF_WARN_AKA("%hhu", "unsigned char", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hhu", "unsigned char", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hhu", "unsigned char", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hhu", "unsigned char", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hhu", "unsigned char", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hhu", "unsigned char", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhu", "unsigned char", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhu", "unsigned char", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhu", "unsigned char", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhu", "unsigned char", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhu", "unsigned char", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%hhx", "unsigned char", "bool");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "char");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "signed char");
        TEST_PRINTF_NOWARN("%hhx", "unsigned char", "unsigned char");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "signed short");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "unsigned short");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "signed int");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "unsigned int");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "signed long");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "unsigned long");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "signed long long");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "unsigned long long");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "float");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "double");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "long double");
        TEST_PRINTF_WARN("%hhx", "unsigned char", "void *");
        TEST_PRINTF_WARN_AKA("%hhx", "unsigned char", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hhx", "unsigned char", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hhx", "unsigned char", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hhx", "unsigned char", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%hhx", "unsigned char", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%hhx", "unsigned char", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhx", "unsigned char", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhx", "unsigned char", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhx", "unsigned char", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhx", "unsigned char", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%hhx", "unsigned char", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%Lu", "unsigned long long", "bool");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "char");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "signed char");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "unsigned char");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "signed short");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "unsigned short");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "signed int");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "unsigned int");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "signed long");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "unsigned long");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "signed long long");
        TEST_PRINTF_NOWARN("%Lu", "unsigned long long", "unsigned long long");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "float");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "double");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "long double");
        TEST_PRINTF_WARN("%Lu", "unsigned long long", "void *");
        TEST_PRINTF_WARN_AKA_WIN32("%Lu", "unsigned long long", "size_t", "unsigned long");
        TEST_PRINTF_WARN_AKA("%Lu", "unsigned long long", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Lu", "unsigned long long", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%Lu", "unsigned long long", "unsigned ptrdiff_t", "unsigned long");
        TEST_PRINTF_WARN_AKA("%Lu", "unsigned long long", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%Lu", "unsigned long long", "uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA("%Lu", "unsigned long long", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%Lu", "unsigned long long", "uintptr_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%Lu", "unsigned long long", "std::size_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP("%Lu", "unsigned long long", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lu", "unsigned long long", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lu", "unsigned long long", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%Lu", "unsigned long long", "std::uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP("%Lu", "unsigned long long", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%Lu", "unsigned long long", "std::uintptr_t", "unsigned long");

        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "bool");
        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "char");
        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "signed char");
        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "unsigned char");
        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "signed short");
        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "unsigned short");
        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "signed int");
        //TODO TEST_PRINTF_WARN("%Lx", "unsigned long long", "unsigned int");
        TEST_PRINTF_WARN("%Lx", "unsigned long long", "signed long");
        TEST_PRINTF_WARN("%Lx", "unsigned long long", "unsigned long");
        TEST_PRINTF_WARN("%Lx", "unsigned long long", "signed long long");
        //TODO TEST_PRINTF_NOWARN("%Lx", "unsigned long long", "unsigned long long");
        TEST_PRINTF_WARN("%Lx", "unsigned long long", "float");
        TEST_PRINTF_WARN("%Lx", "unsigned long long", "double");
        TEST_PRINTF_WARN("%Lx", "unsigned long long", "long double");
        TEST_PRINTF_WARN("%Lx", "unsigned long long", "void *");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Lx", "unsigned long long", "uintptr_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lx", "unsigned long long", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lx", "unsigned long long", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lx", "unsigned long long", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lx", "unsigned long long", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lx", "unsigned long long", "std::uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lx", "unsigned long long", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Lx", "unsigned long long", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%ju", "uintmax_t", "bool");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "char");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "signed char");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "unsigned char");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "signed short");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "unsigned short");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "signed int");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "unsigned int");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "signed long");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "unsigned long");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "signed long long");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "unsigned long long");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "float");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "double");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "long double");
        TEST_PRINTF_WARN("%ju", "uintmax_t", "void *");
        TEST_PRINTF_WARN_AKA("%ju", "uintmax_t", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%ju", "uintmax_t", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%ju", "uintmax_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%ju", "uintmax_t", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%ju", "uintmax_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_NOWARN("%ju", "uintmax_t", "uintmax_t");
        TEST_PRINTF_WARN_AKA_CPP("%ju", "uintmax_t", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%ju", "uintmax_t", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%ju", "uintmax_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%ju", "uintmax_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%ju", "uintmax_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%jx", "uintmax_t", "bool");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "char");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "signed char");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "unsigned char");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "signed short");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "unsigned short");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "signed int");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "unsigned int");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "signed long");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "unsigned long");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "signed long long");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "unsigned long long");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "float");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "double");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "long double");
        TEST_PRINTF_WARN("%jx", "uintmax_t", "void *");
        TEST_PRINTF_WARN_AKA("%jx", "uintmax_t", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%jx", "uintmax_t", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%jx", "uintmax_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%jx", "uintmax_t", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%jx", "uintmax_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_NOWARN("%jx", "uintmax_t", "uintmax_t");
        TEST_PRINTF_WARN_AKA_CPP("%jx", "uintmax_t", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%jx", "uintmax_t", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%jx", "uintmax_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%jx", "uintmax_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%jx", "uintmax_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN_AKA("%zd", "ssize_t", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%zi", "ssize_t", "size_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%zu", "size_t", "bool");
        TEST_PRINTF_WARN("%zu", "size_t", "char");
        TEST_PRINTF_WARN("%zu", "size_t", "signed char");
        TEST_PRINTF_WARN("%zu", "size_t", "unsigned char");
        TEST_PRINTF_WARN("%zu", "size_t", "signed short");
        TEST_PRINTF_WARN("%zu", "size_t", "unsigned short");
        TEST_PRINTF_WARN("%zu", "size_t", "signed int");
        TEST_PRINTF_WARN("%zu", "size_t", "unsigned int");
        TEST_PRINTF_WARN("%zu", "size_t", "signed long");
        TEST_PRINTF_WARN("%zu", "size_t", "unsigned long");
        TEST_PRINTF_WARN("%zu", "size_t", "signed long long");
        TEST_PRINTF_WARN("%zu", "size_t", "unsigned long long");
        TEST_PRINTF_WARN("%zu", "size_t", "float");
        TEST_PRINTF_WARN("%zu", "size_t", "double");
        TEST_PRINTF_WARN("%zu", "size_t", "long double");
        TEST_PRINTF_WARN("%zu", "size_t", "void *");
        TEST_PRINTF_NOWARN("%zu", "size_t", "size_t");
        TEST_PRINTF_WARN_AKA("%zu", "size_t", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%zu", "size_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%zu", "size_t", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%zu", "size_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%zu", "size_t", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_NOWARN_CPP("%zu", "size_t", "std::size_t");
        TEST_PRINTF_WARN_AKA_CPP("%zu", "size_t", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%zu", "size_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%zu", "size_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%zu", "size_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%zx", "size_t", "bool");
        TEST_PRINTF_WARN("%zx", "size_t", "char");
        TEST_PRINTF_WARN("%zx", "size_t", "signed char");
        TEST_PRINTF_WARN("%zx", "size_t", "unsigned char");
        TEST_PRINTF_WARN("%zx", "size_t", "signed short");
        TEST_PRINTF_WARN("%zx", "size_t", "unsigned short");
        TEST_PRINTF_WARN("%zx", "size_t", "signed int");
        TEST_PRINTF_WARN("%zx", "size_t", "unsigned int");
        TEST_PRINTF_WARN("%zx", "size_t", "signed long");
        TEST_PRINTF_WARN("%zx", "size_t", "unsigned long");
        TEST_PRINTF_WARN("%zx", "size_t", "signed long long");
        TEST_PRINTF_WARN("%zx", "size_t", "unsigned long long");
        TEST_PRINTF_WARN("%zx", "size_t", "float");
        TEST_PRINTF_WARN("%zx", "size_t", "double");
        TEST_PRINTF_WARN("%zx", "size_t", "long double");
        TEST_PRINTF_WARN("%zx", "size_t", "void *");
        TEST_PRINTF_NOWARN("%zx", "size_t", "size_t");
        TEST_PRINTF_WARN_AKA("%zx", "size_t", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%zx", "size_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%zx", "size_t", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%zx", "size_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%zx", "size_t", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_NOWARN_CPP("%zx", "size_t", "std::size_t");
        TEST_PRINTF_WARN_AKA_CPP("%zx", "size_t", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%zx", "size_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%zx", "size_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%zx", "size_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "bool");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "char");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "signed char");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "unsigned char");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "signed short");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "unsigned short");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "signed int");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "unsigned int");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "signed long");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "unsigned long");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "signed long long");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "unsigned long long");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "float");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "double");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "long double");
        TEST_PRINTF_WARN("%tu", "unsigned ptrdiff_t", "void *");
        TEST_PRINTF_WARN_AKA("%tu", "unsigned ptrdiff_t", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%tu", "unsigned ptrdiff_t", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%tu", "unsigned ptrdiff_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_NOWARN("%tu", "unsigned ptrdiff_t", "unsigned ptrdiff_t");
        TEST_PRINTF_WARN_AKA("%tu", "unsigned ptrdiff_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%tu", "unsigned ptrdiff_t", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%tu", "unsigned ptrdiff_t", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%tu", "unsigned ptrdiff_t", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%tu", "unsigned ptrdiff_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%tu", "unsigned ptrdiff_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%tu", "unsigned ptrdiff_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "bool");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "char");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "signed char");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "unsigned char");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "signed short");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "unsigned short");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "signed int");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "unsigned int");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "signed long");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "unsigned long");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "signed long long");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "unsigned long long");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "float");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "double");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "long double");
        TEST_PRINTF_WARN("%tx", "unsigned ptrdiff_t", "void *");
        TEST_PRINTF_WARN_AKA("%tx", "unsigned ptrdiff_t", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%tx", "unsigned ptrdiff_t", "ssize_t", "signed long", "signed long long");
        //TODO TEST_PRINTF_WARN_AKA("%tx", "unsigned ptrdiff_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_NOWARN("%tx", "unsigned ptrdiff_t", "unsigned ptrdiff_t");
        TEST_PRINTF_WARN_AKA("%tx", "unsigned ptrdiff_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%tx", "unsigned ptrdiff_t", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%tx", "unsigned ptrdiff_t", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%tx", "unsigned ptrdiff_t", "std::ssize_t", "signed long", "signed long long");
        //TODO TEST_PRINTF_WARN_AKA_CPP("%tx", "unsigned ptrdiff_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%tx", "unsigned ptrdiff_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%tx", "unsigned ptrdiff_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%Iu", "size_t", "bool");
        TEST_PRINTF_WARN("%Iu", "size_t", "char");
        TEST_PRINTF_WARN("%Iu", "size_t", "signed char");
        TEST_PRINTF_WARN("%Iu", "size_t", "unsigned char");
        TEST_PRINTF_WARN("%Iu", "size_t", "signed short");
        TEST_PRINTF_WARN("%Iu", "size_t", "unsigned short");
        TEST_PRINTF_WARN("%Iu", "size_t", "signed int");
        TEST_PRINTF_WARN("%Iu", "size_t", "unsigned int");
        TEST_PRINTF_WARN("%Iu", "size_t", "signed long");
        TEST_PRINTF_WARN("%Iu", "size_t", "unsigned long");
        TEST_PRINTF_WARN("%Iu", "size_t", "signed long long");
        TEST_PRINTF_WARN("%Iu", "size_t", "unsigned long long");
        TEST_PRINTF_WARN("%Iu", "size_t", "float");
        TEST_PRINTF_WARN("%Iu", "size_t", "double");
        TEST_PRINTF_WARN("%Iu", "size_t", "long double");
        TEST_PRINTF_WARN("%Iu", "size_t", "void *");
        TEST_PRINTF_NOWARN("%Iu", "size_t", "size_t");
        TEST_PRINTF_WARN_AKA("%Iu", "size_t", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Iu", "size_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Iu", "size_t", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%Iu", "size_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Iu", "size_t", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%Iu", "size_t", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Iu", "size_t", "uintptr_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_NOWARN_CPP("%Iu", "size_t", "std::size_t");
        TEST_PRINTF_WARN_AKA_CPP("%Iu", "size_t", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Iu", "size_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Iu", "size_t", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Iu", "size_t", "std::uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%Iu", "size_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Iu", "size_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%Ix", "size_t", "bool");
        TEST_PRINTF_WARN("%Ix", "size_t", "char");
        TEST_PRINTF_WARN("%Ix", "size_t", "signed char");
        TEST_PRINTF_WARN("%Ix", "size_t", "unsigned char");
        TEST_PRINTF_WARN("%Ix", "size_t", "signed short");
        TEST_PRINTF_WARN("%Ix", "size_t", "unsigned short");
        TEST_PRINTF_WARN("%Ix", "size_t", "signed int");
        TEST_PRINTF_WARN("%Ix", "size_t", "unsigned int");
        TEST_PRINTF_WARN("%Ix", "size_t", "signed long");
        TEST_PRINTF_WARN("%Ix", "size_t", "unsigned long");
        TEST_PRINTF_WARN("%Ix", "size_t", "signed long long");
        TEST_PRINTF_WARN("%Ix", "size_t", "unsigned long long");
        TEST_PRINTF_WARN("%Ix", "size_t", "float");
        TEST_PRINTF_WARN("%Ix", "size_t", "double");
        TEST_PRINTF_WARN("%Ix", "size_t", "long double");
        TEST_PRINTF_WARN("%Ix", "size_t", "void *");
        TEST_PRINTF_NOWARN("%Ix", "size_t", "size_t");
        TEST_PRINTF_WARN_AKA("%Ix", "size_t", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Ix", "size_t", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Ix", "size_t", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%Ix", "size_t", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Ix", "size_t", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%Ix", "size_t", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%Ix", "size_t", "uintptr_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_NOWARN_CPP("%Ix", "size_t", "std::size_t");
        TEST_PRINTF_WARN_AKA_CPP("%Ix", "size_t", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Ix", "size_t", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Ix", "size_t", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Ix", "size_t", "std::uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%Ix", "size_t", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%Ix", "size_t", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "bool");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "char");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "signed char");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "unsigned char");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "signed short");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "unsigned short");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "signed int");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "unsigned int");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "signed long");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "unsigned long");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "signed long long");
        TEST_PRINTF_NOWARN("%I64u", "unsigned __int64", "unsigned long long");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "float");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "double");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "long double");
        TEST_PRINTF_WARN("%I64u", "unsigned __int64", "void *");
        TEST_PRINTF_WARN_AKA_WIN32("%I64u", "unsigned __int64", "size_t", "unsigned long");
        TEST_PRINTF_WARN_AKA("%I64u", "unsigned __int64", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I64u", "unsigned __int64", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64u", "unsigned __int64", "unsigned ptrdiff_t", "unsigned long");
        TEST_PRINTF_WARN_AKA("%I64u", "unsigned __int64", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64u", "unsigned __int64", "uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA("%I64u", "unsigned __int64", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64u", "unsigned __int64", "uintptr_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64u", "unsigned __int64", "std::size_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP("%I64u", "unsigned __int64", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I64u", "unsigned __int64", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I64u", "unsigned __int64", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64u", "unsigned __int64", "std::uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP("%I64u", "unsigned __int64", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64u", "unsigned __int64", "std::uintptr_t", "unsigned long");

        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "bool");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "char");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "signed char");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "unsigned char");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "signed short");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "unsigned short");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "signed int");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "unsigned int");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "signed long");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "unsigned long");
        //TODO TEST_PRINTF_WARN("%I64x", "unsigned __int64", "signed long long");
        TEST_PRINTF_NOWARN("%I64x", "unsigned __int64", "unsigned long long");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "float");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "double");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "long double");
        TEST_PRINTF_WARN("%I64x", "unsigned __int64", "void *");
        //TODO TEST_PRINTF_WARN("%I64x", "unsigned __int64", "size_t");
        TEST_PRINTF_WARN_AKA_WIN32("%I64x", "unsigned __int64", "ssize_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64x", "unsigned __int64", "ptrdiff_t", "signed long");
        //TODO TEST_PRINTF_NOWARN("%I64x", "unsigned __int64", "unsigned __int64");
        // TODO TEST_PRINTF_WARN("%I64x", "unsigned __int64", "__int64");
        TEST_PRINTF_WARN_AKA_WIN32("%I64x", "unsigned __int64", "unsigned ptrdiff_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64x", "unsigned __int64", "intmax_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64x", "unsigned __int64", "uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64x", "unsigned __int64", "intptr_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64x", "unsigned __int64", "uintptr_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64x", "unsigned __int64", "std::size_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64x", "unsigned __int64", "std::ssize_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64x", "unsigned __int64", "std::ptrdiff_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64x", "unsigned __int64", "std::intmax_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64x", "unsigned __int64", "std::uintmax_t", "unsigned long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64x", "unsigned __int64", "std::intptr_t", "signed long");
        TEST_PRINTF_WARN_AKA_CPP_WIN32("%I64x", "unsigned __int64", "std::uintptr_t", "unsigned long");

        TEST_PRINTF_WARN("%I64d", "__int64", "bool");
        TEST_PRINTF_WARN("%I64d", "__int64", "signed char");
        TEST_PRINTF_WARN("%I64d", "__int64", "unsigned char");
        TEST_PRINTF_WARN("%I64d", "__int64", "void *");
        // TODO TEST_PRINTF_WARN("%I64d", "__int64", "size_t");
        TEST_PRINTF_WARN_AKA_WIN32("%I64d", "__int64", "intmax_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64d", "__int64", "ssize_t", "signed long");
        TEST_PRINTF_WARN_AKA_WIN32("%I64d", "__int64", "ptrdiff_t", "signed long");
        TEST_PRINTF_NOWARN("%I64d", "__int64", "__int64");

        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "bool");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "char");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "signed char");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "unsigned char");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "signed short");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "unsigned short");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "signed int");
        TEST_PRINTF_NOWARN("%I32u", "unsigned __int32", "unsigned int");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "signed long");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "unsigned long");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "signed long long");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "unsigned long long");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "float");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "double");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "long double");
        TEST_PRINTF_WARN("%I32u", "unsigned __int32", "void *");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32u", "unsigned __int32", "uintptr_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32u", "unsigned __int32", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32u", "unsigned __int32", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32u", "unsigned __int32", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32u", "unsigned __int32", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32u", "unsigned __int32", "std::uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32u", "unsigned __int32", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32u", "unsigned __int32", "std::uintptr_t", "unsigned long", "unsigned long long");

        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "bool");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "char");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "signed char");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "unsigned char");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "signed short");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "unsigned short");
        //TODO TEST_PRINTF_WARN("%I32x", "unsigned __int32", "signed int");
        TEST_PRINTF_NOWARN("%I32x", "unsigned __int32", "unsigned int");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "signed long");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "unsigned long");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "signed long long");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "unsigned long long");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "float");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "double");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "long double");
        TEST_PRINTF_WARN("%I32x", "unsigned __int32", "void *");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "unsigned ptrdiff_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA("%I32x", "unsigned __int32", "uintptr_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32x", "unsigned __int32", "std::size_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32x", "unsigned __int32", "std::ssize_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32x", "unsigned __int32", "std::ptrdiff_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32x", "unsigned __int32", "std::intmax_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32x", "unsigned __int32", "std::uintmax_t", "unsigned long", "unsigned long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32x", "unsigned __int32", "std::intptr_t", "signed long", "signed long long");
        TEST_PRINTF_WARN_AKA_CPP("%I32x", "unsigned __int32", "std::uintptr_t", "unsigned long", "unsigned long long");
    }

    void testPosixPrintfScanfParameterPosition() { // #4900  - No support for parameters in format strings
        check("void foo() {"
              "  int bar;"
              "  printf(\"%1$d\", 1);"
              "  printf(\"%1$d, %d, %1$d\", 1, 2);"
              "  scanf(\"%1$d\", &bar);"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "  int bar;\n"
              "  printf(\"%1$d\");\n"
              "  printf(\"%1$d, %d, %4$d\", 1, 2, 3);\n"
              "  scanf(\"%2$d\", &bar);\n"
              "  printf(\"%0$f\", 0.0);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:3:3]: (error) printf format string requires 1 parameter but only 0 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:4:3]: (warning) printf: referencing parameter 4 while 3 arguments given [wrongPrintfScanfParameterPositionError]\n"
                      "[test.cpp:5:3]: (warning) scanf: referencing parameter 2 while 1 arguments given [wrongPrintfScanfParameterPositionError]\n"
                      "[test.cpp:6:3]: (warning) printf: parameter positions start at 1, not 0 [wrongPrintfScanfParameterPositionError]\n"
                      "", errout_str());
    }


    void testMicrosoftPrintfArgument() {
        check("void foo() {\n"
              "    size_t s;\n"
              "    ptrdiff_t p;\n"
              "    __int32 i32;\n"
              "    unsigned __int32 u32;\n"
              "    __int64 i64;\n"
              "    unsigned __int64 u64;\n"
              "    printf(\"%Id %Iu %Ix\", s, s, s);\n"
              "    printf(\"%Id %Iu %Ix\", p, p, p);\n"
              "    printf(\"%I32d %I32u %I32x\", i32, i32, i32);\n"
              "    printf(\"%I32d %I32u %I32x\", u32, u32, u32);\n"
              "    printf(\"%I64d %I64u %I64x\", i64, i64, i64);\n"
              "    printf(\"%I64d %I64u %I64x\", u64, u64, u64);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:8:5]: (portability) %Id in format string (no. 1) requires 'ptrdiff_t' but the argument type is 'size_t {aka unsigned long}'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:9:5]: (portability) %Iu in format string (no. 2) requires 'size_t' but the argument type is 'ptrdiff_t {aka signed long}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:9:5]: (portability) %Ix in format string (no. 3) requires 'size_t' but the argument type is 'ptrdiff_t {aka signed long}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:10:5]: (portability) %I32u in format string (no. 2) requires 'unsigned __int32' but the argument type is '__int32 {aka signed int}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:11:5]: (portability) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned __int32 {aka unsigned int}'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:12:5]: (portability) %I64u in format string (no. 2) requires 'unsigned __int64' but the argument type is '__int64 {aka signed long long}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:13:5]: (portability) %I64d in format string (no. 1) requires '__int64' but the argument type is 'unsigned __int64 {aka unsigned long long}'. [invalidPrintfArgType_sint]\n", errout_str());

        check("void foo() {\n"
              "    size_t s;\n"
              "    ptrdiff_t p;\n"
              "    __int32 i32;\n"
              "    unsigned __int32 u32;\n"
              "    __int64 i64;\n"
              "    unsigned __int64 u64;\n"
              "    printf(\"%Id %Iu %Ix\", s, s, s);\n"
              "    printf(\"%Id %Iu %Ix\", p, p, p);\n"
              "    printf(\"%I32d %I32u %I32x\", i32, i32, i32);\n"
              "    printf(\"%I32d %I32u %I32x\", u32, u32, u32);\n"
              "    printf(\"%I64d %I64u %I64x\", i64, i64, i64);\n"
              "    printf(\"%I64d %I64u %I64x\", u64, u64, u64);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:8:5]: (portability) %Id in format string (no. 1) requires 'ptrdiff_t' but the argument type is 'size_t {aka unsigned long long}'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:9:5]: (portability) %Iu in format string (no. 2) requires 'size_t' but the argument type is 'ptrdiff_t {aka signed long long}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:9:5]: (portability) %Ix in format string (no. 3) requires 'size_t' but the argument type is 'ptrdiff_t {aka signed long long}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:10:5]: (portability) %I32u in format string (no. 2) requires 'unsigned __int32' but the argument type is '__int32 {aka signed int}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:11:5]: (portability) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned __int32 {aka unsigned int}'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:12:5]: (portability) %I64u in format string (no. 2) requires 'unsigned __int64' but the argument type is '__int64 {aka signed long long}'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:13:5]: (portability) %I64d in format string (no. 1) requires '__int64' but the argument type is 'unsigned __int64 {aka unsigned long long}'. [invalidPrintfArgType_sint]\n", errout_str());

        check("void foo() {\n"
              "    size_t s;\n"
              "    int i;\n"
              "    printf(\"%I\", s);\n"
              "    printf(\"%I6\", s);\n"
              "    printf(\"%I6x\", s);\n"
              "    printf(\"%I16\", s);\n"
              "    printf(\"%I16x\", s);\n"
              "    printf(\"%I32\", s);\n"
              "    printf(\"%I64\", s);\n"
              "    printf(\"%I%i\", s, i);\n"
              "    printf(\"%I6%i\", s, i);\n"
              "    printf(\"%I6x%i\", s, i);\n"
              "    printf(\"%I16%i\", s, i);\n"
              "    printf(\"%I16x%i\", s, i);\n"
              "    printf(\"%I32%i\", s, i);\n"
              "    printf(\"%I64%i\", s, i);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:5:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:6:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:7:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:8:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:9:5]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:10:5]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:11:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:12:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:13:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:14:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:15:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:16:5]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:17:5]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n", errout_str());

        // ticket #5264
        check("void foo(LPARAM lp, WPARAM wp, LRESULT lr) {\n"
              "    printf(\"%Ix %Ix %Ix\", lp, wp, lr);\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("", errout_str());

        check("void foo(LPARAM lp, WPARAM wp, LRESULT lr) {\n"
              "    printf(\"%Ix %Ix %Ix\", lp, wp, lr);\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("", errout_str());

        check("void foo(UINT32 a, ::UINT32 b, Fred::UINT32 c) {\n"
              "    printf(\"%d %d %d\", a, b, c);\n"
              "};\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:2:5]: (portability) %d in format string (no. 1) requires 'int' but the argument type is 'UINT32 {aka unsigned int}'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:2:5]: (portability) %d in format string (no. 2) requires 'int' but the argument type is 'UINT32 {aka unsigned int}'. [invalidPrintfArgType_sint]\n", errout_str());

        check("void foo(LPCVOID a, ::LPCVOID b, Fred::LPCVOID c) {\n"
              "    printf(\"%d %d %d\", a, b, c);\n"
              "};\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:2:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'const void *'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:2:5]: (warning) %d in format string (no. 2) requires 'int' but the argument type is 'const void *'. [invalidPrintfArgType_sint]\n", errout_str());

        check("void foo() {\n"
              "    SSIZE_T s = -2;\n" // In MSVC, SSIZE_T is available in capital letters using #include 
              "    int i;\n"
              "    printf(\"%zd\", s);\n"
              "    printf(\"%zd%i\", s, i);\n"
              "    printf(\"%zu\", s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:6:5]: (portability) %zu in format string (no. 1) requires 'size_t' but the argument type is 'SSIZE_T {aka signed long}'. [invalidPrintfArgType_uint]\n", errout_str());

        check("void foo() {\n"
              "    SSIZE_T s = -2;\n" // In MSVC, SSIZE_T is available in capital letters using #include 
              "    int i;\n"
              "    printf(\"%zd\", s);\n"
              "    printf(\"%zd%i\", s, i);\n"
              "    printf(\"%zu\", s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:6:5]: (portability) %zu in format string (no. 1) requires 'size_t' but the argument type is 'SSIZE_T {aka signed long long}'. [invalidPrintfArgType_uint]\n", errout_str());

        check("void foo() {\n"
              "    SSIZE_T s = -2;\n" // Under Unix, ssize_t has to be written in small letters. Not Cppcheck, but the compiler will report this.
              "    int i;\n"
              "    printf(\"%zd\", s);\n"
              "    printf(\"%zd%i\", s, i);\n"
              "    printf(\"%zu\", s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "    typedef SSIZE_T ssize_t;\n" // Test using typedef
              "    ssize_t s = -2;\n"
              "    int i;\n"
              "    printf(\"%zd\", s);\n"
              "    printf(\"%zd%i\", s, i);\n"
              "    printf(\"%zu\", s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:7:5]: (portability) %zu in format string (no. 1) requires 'size_t' but the argument type is 'SSIZE_T {aka signed long long}'. [invalidPrintfArgType_uint]\n", errout_str());

    }

    void testMicrosoftScanfArgument() {
        check("void foo() {\n"
              "    size_t s;\n"
              "    ptrdiff_t p;\n"
              "    __int32 i32;\n"
              "    unsigned __int32 u32;\n"
              "    __int64 i64;\n"
              "    unsigned __int64 u64;\n"
              "    scanf(\"%Id %Iu %Ix\", &s, &s, &s);\n"
              "    scanf(\"%Id %Iu %Ix\", &p, &p, &p);\n"
              "    scanf(\"%I32d %I32u %I32x\", &i32, &i32, &i32);\n"
              "    scanf(\"%I32d %I32u %I32x\", &u32, &u32, &u32);\n"
              "    scanf(\"%I64d %I64u %I64x\", &i64, &i64, &i64);\n"
              "    scanf(\"%I64d %I64u %I64x\", &u64, &u64, &u64);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:8:5]: (portability) %Id in format string (no. 1) requires 'ptrdiff_t *' but the argument type is 'size_t * {aka unsigned long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:9:5]: (portability) %Iu in format string (no. 2) requires 'size_t *' but the argument type is 'ptrdiff_t * {aka signed long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:9:5]: (portability) %Ix in format string (no. 3) requires 'size_t *' but the argument type is 'ptrdiff_t * {aka signed long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:10:5]: (portability) %I32u in format string (no. 2) requires 'unsigned __int32 *' but the argument type is '__int32 * {aka signed int *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:10:5]: (portability) %I32x in format string (no. 3) requires 'unsigned __int32 *' but the argument type is '__int32 * {aka signed int *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:11:5]: (portability) %I32d in format string (no. 1) requires '__int32 *' but the argument type is 'unsigned __int32 * {aka unsigned int *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:12:5]: (portability) %I64u in format string (no. 2) requires 'unsigned __int64 *' but the argument type is '__int64 * {aka signed long long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:12:5]: (portability) %I64x in format string (no. 3) requires 'unsigned __int64 *' but the argument type is '__int64 * {aka signed long long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:13:5]: (portability) %I64d in format string (no. 1) requires '__int64 *' but the argument type is 'unsigned __int64 * {aka unsigned long long *}'. [invalidScanfArgType_int]\n", errout_str());

        check("void foo() {\n"
              "    size_t s;\n"
              "    ptrdiff_t p;\n"
              "    __int32 i32;\n"
              "    unsigned __int32 u32;\n"
              "    __int64 i64;\n"
              "    unsigned __int64 u64;\n"
              "    scanf(\"%Id %Iu %Ix\", &s, &s, &s);\n"
              "    scanf(\"%Id %Iu %Ix\", &p, &p, &p);\n"
              "    scanf(\"%I32d %I32u %I32x\", &i32, &i32, &i32);\n"
              "    scanf(\"%I32d %I32u %I32x\", &u32, &u32, &u32);\n"
              "    scanf(\"%I64d %I64u %I64x\", &i64, &i64, &i64);\n"
              "    scanf(\"%I64d %I64u %I64x\", &u64, &u64, &u64);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:8:5]: (portability) %Id in format string (no. 1) requires 'ptrdiff_t *' but the argument type is 'size_t * {aka unsigned long long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:9:5]: (portability) %Iu in format string (no. 2) requires 'size_t *' but the argument type is 'ptrdiff_t * {aka signed long long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:9:5]: (portability) %Ix in format string (no. 3) requires 'size_t *' but the argument type is 'ptrdiff_t * {aka signed long long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:10:5]: (portability) %I32u in format string (no. 2) requires 'unsigned __int32 *' but the argument type is '__int32 * {aka signed int *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:10:5]: (portability) %I32x in format string (no. 3) requires 'unsigned __int32 *' but the argument type is '__int32 * {aka signed int *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:11:5]: (portability) %I32d in format string (no. 1) requires '__int32 *' but the argument type is 'unsigned __int32 * {aka unsigned int *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:12:5]: (portability) %I64u in format string (no. 2) requires 'unsigned __int64 *' but the argument type is '__int64 * {aka signed long long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:12:5]: (portability) %I64x in format string (no. 3) requires 'unsigned __int64 *' but the argument type is '__int64 * {aka signed long long *}'. [invalidScanfArgType_int]\n"
                      "[test.cpp:13:5]: (portability) %I64d in format string (no. 1) requires '__int64 *' but the argument type is 'unsigned __int64 * {aka unsigned long long *}'. [invalidScanfArgType_int]\n", errout_str());

        check("void foo() {\n"
              "    size_t s;\n"
              "    int i;\n"
              "    scanf(\"%I\", &s);\n"
              "    scanf(\"%I6\", &s);\n"
              "    scanf(\"%I6x\", &s);\n"
              "    scanf(\"%I16\", &s);\n"
              "    scanf(\"%I16x\", &s);\n"
              "    scanf(\"%I32\", &s);\n"
              "    scanf(\"%I64\", &s);\n"
              "    scanf(\"%I%i\", &s, &i);\n"
              "    scanf(\"%I6%i\", &s, &i);\n"
              "    scanf(\"%I6x%i\", &s, &i);\n"
              "    scanf(\"%I16%i\", &s, &i);\n"
              "    scanf(\"%I16x%i\", &s, &i);\n"
              "    scanf(\"%I32%i\", &s, &i);\n"
              "    scanf(\"%I64%i\", &s, &i);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:5:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:6:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:7:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:8:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:9:5]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:10:5]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:11:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:12:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:13:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:14:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:15:5]: (warning) 'I' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:16:5]: (warning) 'I32' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n"
                      "[test.cpp:17:5]: (warning) 'I64' in format string (no. 1) is a length modifier and cannot be used without a conversion specifier. [invalidLengthModifierError]\n", errout_str());

        check("void foo() {\n"
              "    SSIZE_T s;\n" // In MSVC, SSIZE_T is available in capital letters using #include 
              "    int i;\n"
              "    scanf(\"%zd\", &s);\n"
              "    scanf(\"%zd%i\", &s, &i);\n"
              "    scanf(\"%zu\", &s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:6:5]: (portability) %zu in format string (no. 1) requires 'size_t *' but the argument type is 'SSIZE_T * {aka signed long *}'. [invalidScanfArgType_int]\n", errout_str());

        check("void foo() {\n"
              "    SSIZE_T s;\n" // In MSVC, SSIZE_T is available in capital letters using #include 
              "    int i;\n"
              "    scanf(\"%zd\", &s);\n"
              "    scanf(\"%zd%i\", &s, &i);\n"
              "    scanf(\"%zu\", &s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:6:5]: (portability) %zu in format string (no. 1) requires 'size_t *' but the argument type is 'SSIZE_T * {aka signed long long *}'. [invalidScanfArgType_int]\n", errout_str());

        check("void foo() {\n"
              "    SSIZE_T s;\n" // Under Unix, ssize_t has to be written in small letters. Not Cppcheck, but the compiler will report this.
              "    int i;\n"
              "    scanf(\"%zd\", &s);\n"
              "    scanf(\"%zd%i\", &s, &i);\n"
              "    scanf(\"%zu\", &s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "    typedef SSIZE_T ssize_t;\n" // Test using typedef
              "    ssize_t s;\n"
              "    int i;\n"
              "    scanf(\"%zd\", &s);\n"
              "    scanf(\"%zd%i\", &s, &i);\n"
              "    scanf(\"%zu\", &s);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("[test.cpp:7:5]: (portability) %zu in format string (no. 1) requires 'size_t *' but the argument type is 'SSIZE_T * {aka signed long long *}'. [invalidScanfArgType_int]\n", errout_str());

    }

    void testMicrosoftCStringFormatArguments() { // ticket #4920
        check("void foo() {\n"
              "    unsigned __int32 u32;\n"
              "    String string;\n"
              "    string.Format(\"%I32d\", u32);\n"
              "    string.AppendFormat(\"%I32d\", u32);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "    unsigned __int32 u32;\n"
              "    CString string;\n"
              "    string.Format(\"%I32d\", u32);\n"
              "    string.AppendFormat(\"%I32d\", u32);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix32));
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "    unsigned __int32 u32;\n"
              "    CString string;\n"
              "    string.Format(\"%I32d\", u32);\n"
              "    string.AppendFormat(\"%I32d\", u32);\n"
              "    CString::Format(\"%I32d\", u32);\n"
              "}", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4:12]: (portability) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned __int32 {aka unsigned int}'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:12]: (portability) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned __int32 {aka unsigned int}'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:6:14]: (portability) %I32d in format string (no. 1) requires '__int32' but the argument type is 'unsigned __int32 {aka unsigned int}'. [invalidPrintfArgType_sint]\n", errout_str());
    }

    void testMicrosoftSecurePrintfArgument() {
        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _tprintf_s(_T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) _tprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _tprintf_s(_T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) _tprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    printf_s(\"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) printf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    wprintf_s(L\"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) wprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    TCHAR str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _stprintf_s(str, sizeof(str) / sizeof(TCHAR), _T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) _stprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    TCHAR str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _stprintf_s(str, sizeof(str) / sizeof(TCHAR), _T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) _stprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    char str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    sprintf_s(str, sizeof(str), \"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) sprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    char str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    sprintf_s(str, \"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) sprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    wchar_t str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    swprintf_s(str, sizeof(str) / sizeof(wchar_t), L\"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) swprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    wchar_t str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    swprintf_s(str, L\"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) swprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    TCHAR str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _sntprintf_s(str, sizeof(str) / sizeof(TCHAR), _TRUNCATE, _T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) _sntprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    TCHAR str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _sntprintf_s(str, sizeof(str) / sizeof(TCHAR), _TRUNCATE, _T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) _sntprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    char str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _snprintf_s(str, sizeof(str), _TRUNCATE, \"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) _snprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    wchar_t str[10];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _snwprintf_s(str, sizeof(str) / sizeof(wchar_t), _TRUNCATE, L\"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:5:5]: (warning) _snwprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _ftprintf_s(fp, _T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) _ftprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    _ftprintf_s(fp, _T(\"%d %u\"), u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) _ftprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    fprintf_s(fp, \"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) fprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    fwprintf_s(fp, L\"%d %u\", u, i, 0);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:4:5]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint]\n"
                      "[test.cpp:4:5]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint]\n"
                      "[test.cpp:4:5]: (warning) fwprintf_s format string requires 2 parameters but 3 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    char lineBuffer [600];\n"
              "    const char * const format = \"%15s%17s%17s%17s%17s\";\n"
              "    sprintf_s(lineBuffer, 600, format, \"type\", \"sum\", \"avg\", \"min\", \"max\");\n"
              "    sprintf_s(lineBuffer, format, \"type\", \"sum\", \"avg\", \"min\", \"max\");\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("", errout_str());

        check("void foo() {\n"
              "    const char * const format1 = \"%15s%17s%17s%17s%17s\";\n"
              "    const char format2[] = \"%15s%17s%17s%17s%17s\";\n"
              "    const char * const format3 = format1;\n"
              "    int i = 0;\n"
              "    sprintf_s(lineBuffer, format1, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf_s(lineBuffer, format2, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf_s(lineBuffer, format3, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf(lineBuffer, format1, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf(lineBuffer, format2, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf(lineBuffer, format3, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    printf(format1, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    printf(format2, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    printf(format3, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf_s(lineBuffer, 100, format1, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf_s(lineBuffer, 100, format2, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "    sprintf_s(lineBuffer, 100, format3, \"type\", \"sum\", \"avg\", \"min\", i, 0);\n"
              "}\n", dinit(CheckOptions, $.inconclusive = true, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:6:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:6:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:7:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:7:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:8:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:8:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:9:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:9:5]: (warning) sprintf format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:10:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:10:5]: (warning) sprintf format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:11:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:11:5]: (warning) sprintf format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:12:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:12:5]: (warning) printf format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:13:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:13:5]: (warning) printf format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:14:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:14:5]: (warning) printf format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:15:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:15:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:16:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:16:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n"
                      "[test.cpp:17:5]: (warning) %s in format string (no. 5) requires 'char *' but the argument type is 'signed int'. [invalidPrintfArgType_s]\n"
                      "[test.cpp:17:5]: (warning) sprintf_s format string requires 5 parameters but 6 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("int main()\n"
              "{\n"
              "    double value = 3.14;\n"
              "    const size_t buffer_size = 64;\n"
              "    char buffer[buffer_size];\n"
              "    int precision = 2;\n"
              "    _locale_t locale = _create_locale(LC_ALL, \"C\");\n"
              "    _sprintf_s_l(buffer, buffer_size, \"%.*f\", locale, precision, value);\n"
              "    _free_locale(locale);\n"
              "    return 0;\n"
              "}\n");
        ASSERT_EQUALS("", errout_str());
    }

    void testMicrosoftSecureScanfArgument() {
        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    TCHAR str[10];\n"
              "    _tscanf_s(_T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) _tscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    TCHAR str[10];\n"
              "    _tscanf_s(_T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) _tscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    char str[10];\n"
              "    scanf_s(\"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) scanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    wchar_t str[10];\n"
              "    wscanf_s(L\"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) wscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void f() {\n"
              "  char str[8];\n"
              "  scanf_s(\"%8c\", str, sizeof(str));\n"
              "  scanf_s(\"%9c\", str, sizeof(str));\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:4:3]: (error) Width 9 given in format string (no. 1) is larger than destination buffer 'str[8]', use %8c to prevent overflowing it. [invalidScanfFormatWidth]\n", errout_str());

        check("void foo() {\n"
              "    TCHAR txt[100];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    TCHAR str[10];\n"
              "    _stscanf_s(txt, _T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:6:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) _stscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    TCHAR txt[100];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    TCHAR str[10];\n"
              "    _stscanf_s(txt, _T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:6:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) _stscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    char txt[100];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    char str[10];\n"
              "    sscanf_s(txt, \"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:6:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) sscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    wchar_t txt[100];\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    wchar_t str[10];\n"
              "    swscanf_s(txt, L\"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:6:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:6:5]: (warning) swscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    TCHAR str[10];\n"
              "    _ftscanf_s(fp, _T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) _ftscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    TCHAR str[10];\n"
              "    _ftscanf_s(fp, _T(\"%s %d %u %[a-z]\"), str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) _ftscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    char str[10];\n"
              "    fscanf_s(fp, \"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) fscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo(FILE * fp) {\n"
              "    int i;\n"
              "    unsigned int u;\n"
              "    wchar_t str[10];\n"
              "    fwscanf_s(fp, L\"%s %d %u %[a-z]\", str, 10, &u, &i, str, 10, 0)\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("[test.cpp:5:5]: (warning) %d in format string (no. 2) requires 'int *' but the argument type is 'unsigned int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) %u in format string (no. 3) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int]\n"
                      "[test.cpp:5:5]: (warning) fwscanf_s format string requires 6 parameters but 7 are given. [wrongPrintfScanfArgNum]\n", errout_str());

        check("void foo() {\n"
              "    WCHAR msStr1[5] = {0};\n"
              "    wscanf_s(L\"%4[^-]\", msStr1, _countof(msStr1));\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win32W));
        ASSERT_EQUALS("", errout_str());

        check("void f(const char* c) {\n"
              "    const size_t N = 5;\n"
              "    char buf[N];\n"
              "    sscanf_s(c, \"%4[^.]\", buf, N);\n"
              "}\n", dinit(CheckOptions, $.platform = Platform::Type::Win64));
        ASSERT_EQUALS("", errout_str());
    }

    void testQStringFormatArguments() {
        check("void foo(float f) {\n"
              "    QString string;\n"
              "    string.sprintf(\"%d\", f);\n"
              "}", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:3:12]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'float'. [invalidPrintfArgType_sint]\n", errout_str());

        check("void foo(float f) {\n"
              "    QString string;\n"
              "    string = QString::asprintf(\"%d\", f);\n"
              "}", dinit(CheckOptions, $.platform = Platform::Type::Win32A));
        ASSERT_EQUALS("[test.cpp:3:23]: (warning) %d in format string (no. 1) requires 'int' but the argument type is 'float'. [invalidPrintfArgType_sint]\n", errout_str());
    }

    void testTernary() {  // ticket #6182
        check("void test(const std::string &val) {\n"
              "    printf(\"%s\", val.empty() ? \"I like to eat bananas\" : val.c_str());\n"
              "}");
        ASSERT_EQUALS("", errout_str());
    }

    void testUnsignedConst() {  // ticket #6321
        check("void test() {\n"
              "    unsigned const x = 5;\n"
              "    printf(\"%u\", x);\n"
              "}");
        ASSERT_EQUALS("", errout_str());
    }

    void testAstType() { // ticket #7014
        check("void test() {\n"
              "    printf(\"%c\", \"hello\"[0]);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("void test() {\n"
              "    printf(\"%lld\", (long long)1);\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        check("void test() {\n"
              "    printf(\"%i\", (short *)x);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2:5]: (warning) %i in format string (no. 1) requires 'int' but the argument type is 'signed short *'. [invalidPrintfArgType_sint]\n", errout_str());

        check("int (*fp)();\n" // #7178 - function pointer call
              "void test() {\n"
              "    printf(\"%i\", fp());\n"
              "}");
        ASSERT_EQUALS("", errout_str());
    }

    void testPrintf0WithSuffix() { // ticket #7069
        check("void foo() {\n"
              "    printf(\"%u %lu %llu\", 0U, 0UL, 0ULL);\n"
              "    printf(\"%u %lu %llu\", 0u, 0ul, 0ull);\n"
              "}");
        ASSERT_EQUALS("", errout_str());
    }

    void testReturnValueTypeStdLib() {
        check("void f() {\n"
              "   const char *s = \"0\";\n"
              "   printf(\"%ld%lld\", atol(s), atoll(s));\n"
              "}");
        ASSERT_EQUALS("", errout_str());

        // 8141
        check("void f(int i) {\n"
              "   printf(\"%f\", imaxabs(i));\n"
              "}\n", dinit(CheckOptions, $.portability = true, $.platform = Platform::Type::Unix64));
        ASSERT_EQUALS("[test.cpp:2:4]: (portability) %f in format string (no. 1) requires 'double' but the argument type is 'intmax_t {aka signed long}'. [invalidPrintfArgType_float]\n", errout_str());
    }

    void testPrintfTypeAlias1() {
        check("using INT = int;\n\n"
              "using PINT = INT *;\n"
              "using PCINT = const PINT;\n"
              "INT i;\n"
              "PINT pi;\n"
              "PCINT pci;"
              "void foo() {\n"
              "    printf(\"%d %p %p\", i, pi, pci);\n"
              "};");
        ASSERT_EQUALS("", errout_str());

        check("using INT = int;\n\n"
              "using PINT = INT *;\n"
              "using PCINT = const PINT;\n"
              "INT i;\n"
              "PINT pi;\n"
              "PCINT pci;"
              "void foo() {\n"
              "    printf(\"%f %f %f\", i, pi, pci);\n"
              "};");
        ASSERT_EQUALS("[test.cpp:8:5]: (warning) %f in format string (no. 1) requires 'double' but the argument type is 'signed int'. [invalidPrintfArgType_float]\n"
                      "[test.cpp:8:5]: (warning) %f in format string (no. 2) requires 'double' but the argument type is 'signed int *'. [invalidPrintfArgType_float]\n"
                      "[test.cpp:8:5]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'const signed int *'. [invalidPrintfArgType_float]\n", errout_str());
    }

    void testPrintfAuto() { // #8992
        check("void f() {\n"
              "    auto s = sizeof(int);\n"
              "    printf(\"%zu\", s);\n"
              "    printf(\"%f\", s);\n"
              "}\n", dinit(CheckOptions, $.portability = true));
        ASSERT_EQUALS("[test.cpp:4:5]: (portability) %f in format string (no. 1) requires 'double' but the argument type is 'size_t {aka unsigned long}'. [invalidPrintfArgType_float]\n", errout_str());
    }

    void testPrintfParenthesis() { // #8489
        check("void f(int a) {\n"
              "    printf(\"%f\", (a >> 24) & 0xff);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2:5]: (warning) %f in format string (no. 1) requires 'double' but the argument type is 'signed int'. [invalidPrintfArgType_float]\n", errout_str());

        check("void f(int a) {\n"
              "    printf(\"%f\", 0xff & (a >> 24));\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2:5]: (warning) %f in format string (no. 1) requires 'double' but the argument type is 'signed int'. [invalidPrintfArgType_float]\n", errout_str());

        check("void f(int a) {\n"
              "    printf(\"%f\", ((a >> 24) + 1) & 0xff);\n"
              "}");
        ASSERT_EQUALS("[test.cpp:2:5]: (warning) %f in format string (no. 1) requires 'double' but the argument type is 'signed int'. [invalidPrintfArgType_float]\n", errout_str());
    }

    void testStdDistance() { // #10304
        check("void foo(const std::vector& IO, const int* pio) {\n"
              "const auto Idx = std::distance(&IO.front(), pio);\n"
              "printf(\"Idx = %td\", Idx);\n"
              "}", dinit(CheckOptions, $.portability = true));
        ASSERT_EQUALS("", errout_str());
    }

    void testParameterPack() { // #11289
        check("template  auto f(const char* format, const Args&... args) {\n"
              "    return snprintf(nullptr, 0, format, args...);\n"
              "}\n"
              "void g() {\n"
              "    f(\"%d%d\", 1, 2);\n"
              "}\n");
        ASSERT_EQUALS("", errout_str());
    }

    // TODO: we need to run big tests with a platform that has unsigned chars
    void testDefaultSignInt() { // #13363
        // Platform::defaultSign should only affect char
        const char code[] =
            "void f() {\n"
            "    double d = 1\n;"
            "    printf(\"%i\", int(d));\n"
            "}\n";
        check(code);
        ASSERT_EQUALS("", errout_str());
        check(code, dinit(CheckOptions, $.defaultSign = 's'));
        ASSERT_EQUALS("", errout_str());
        check(code, dinit(CheckOptions, $.defaultSign = 'u'));
        ASSERT_EQUALS("", errout_str());
    }

    void testPrintfWithGeneric() { // #13592
        const char code[] =
            "void f(void) {\n"
            "    float x = 27.0f;\n"
            "    printf(\"%s\\n\", _Generic(x, double: cbrt, float: cbrtf)(x));\n"
            "}\n";
        check(code);
        ASSERT_EQUALS("", errout_str());
    }
};

REGISTER_TEST(TestIO)

Web Proxy Viewer  |  New URL  |  Original Page