Menu

Type-promotion assumptions

2023-01-18
2023-01-22
  • Andrew C Aitchison

    I am looking at this C program

    include <stdio.h></stdio.h>

    include <stdint.h></stdint.h>

    int main(void) {
    uint32_t hk=100*1000;
    uint64_t hk2 = hk * hk;
    uint64_t hk2c = (uint64_t)hk * hk;
    int same = (hk2==hk2c); // V547
    printf("%u^2 = %lu %s %lu\n", hk, hk2c, same ? "==" : "!=", hk2);
    return same==0;
    }


    On Ubuntu 22.10 both GCC and clang generate programs which output
    100000^2 = 10000000000 != 1410065408

    PVS-Studio give warnings:
    General Analysis 100k_squared.c:9 High V547 Expression 'hk2 == hk2c' is always false.
    General Analysis 100k_squared.c:10 Medium V547 Expression 'same' is always false.

    cppcheck v2.9, however, reports
    100k_squared.c:10:45: style: Condition 'same' is always true [knownConditionTrueFalse]
    printf("%u^2 = %lu %s %lu\n", hk, hk2c, same ? "==" : "!=", hk2);
    ... ...

    (so PVS says same is always false but cppcheck says it is always true).

    The issue is that (sadly, but probably in line with the standards)
    the RHS of
    uint64_t hk2 = hk * hk;
    is evaluated as a uint32_t and then assigned, but cppcheck seems to
    miss this subtlety.

    All quoted results appear to be the same if this program, but with
    static_casts, is considered as C++.

    Thanks,

    --
    Andrew C. Aitchison Kendal, UK
    andrew@aitchison.me.uk

     
  • CHR

    CHR - 2023-01-18

    Thanks for reporting, ticket is here: https://trac.cppcheck.net/ticket/11503

     
  • Andrew C Aitchison

    Thanks. I am replying here because I am uneasy about putting passwords into random websites to generate an .htpasswd, so cannot reply to the ticket.

    I am not sure I have explained my issue clearly enough.
    The real bug as I see it is in the C/C++ standards: (uint32) * (uint32) should generate a (uint64)
    (to avoid overflow). Since that is not what the language does, my bug is to expect
    uint32 a = 100000;
    uint64_t b = a * a;

    to set b to 10^10
    I would like cppcheck to warn me that although b could hold the un-truncated product, the product has been truncated to a lower precision than b before being stored.
    I do not particularly expect a warning when on
    unit32 c = a * a;

     
  • Daniel Marjamäki

    I would like cppcheck to warn me that although b could hold the un-truncated product, the product has been truncated to a lower precision than b before being stored.

    Thanks for pointing that out! I agree. hmm.. Cppcheck has such a checking. See this test case:

    https://github.com/danmar/cppcheck/blob/main/test/testtype.cpp#L340

    I am not sure why it doesn't warn. It seems like a false negative.

     
  • CHR

    CHR - 2023-01-20

    That check is specific to type long for some reason, see https://trac.cppcheck.net/ticket/11389#comment:2

     
    • Daniel Marjamäki

      Thanks CHR. I agree with what you say in that ticket. It should check for any such widening conversion.

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.