Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Warning C26454: Arithmetic overflow: '-' operation produces a negative unsigned result at compile time (io.5)

Code analysis:

ON_NOTIFY(TCN_SELCHANGE, IDC_TAB_HISTORY_TYPE,
  &CAssignHistoryDlg::OnTcnSelchangeTabHistoryType)

Warning C26454:

Arithmetic overflow: '-' operation produces a negative unsigned result at compile time (io.5).

The definition of TCN_SELCHANGE is:

#define TCN_FIRST (0U-550U)
#define TCN_SELCHANGE           (TCN_FIRST - 1)

I can't see what else I can do!

like image 299
Andrew Truckle Avatar asked Jul 02 '18 15:07

Andrew Truckle


2 Answers

//windows header file:
#define TCN_FIRST (0U-550U)
#define TCN_SELCHANGE           (TCN_FIRST - 1)

//user file:
...
unsigned int i = TCN_SELCHANGE;

Above code is valid in C++, it should compile without any warning. There is no overflow, that's just meant to be -550U It would be more clear if they wrote it as #define TCN_FIRST 0xFFFFFDDA or 0xFFFFFFFFU-549U

Code Analysis seems to uses a different method and sees an overflow.

Possible solution:

Disable the warning in code:

#pragma warning( push )
#pragma warning( disable : 26454 )

BEGIN_MESSAGE_MAP(CMyDialog, CDialogEx)
    ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnTcnSelchangeTabHistoryType)
END_MESSAGE_MAP()

#pragma warning( pop )

Or, disable the warning in Code Analysis rule
Use the code analysis rule set editor

enter image description here

like image 199
Barmak Shemirani Avatar answered Oct 20 '22 06:10

Barmak Shemirani


You are trying to subtract a larger unsigned value from a smaller unsigned value and it's causing the result to wrap past zero. In your case, I assume TCN_FIRST is defined as 0 so setting TCN_SELCHANGE to one will fix the problem.

You should also be using constexpr or const instead of defines anyway.

According to MSDN:

Arithmetic overflow checks in C++ Core Check

C26451 RESULT_OF_ARITHMETIC_OPERATION_CAST_TO_LARGER_SIZE :[operator] operation wraps past 0 and produces a large unsigned number at compile time. This warning indicates that the subtraction operation produces a negative result which was evaluated in an unsigned context. This causes the result to wrap past 0 and produce a really large unsigned number, which can result in unintended overflows.

1 // Example source:
2 unsigned int negativeunsigned() {
3    const unsigned int x = 1u - 2u; // C26454 reported here
4    return x;
5 }

1 // Corrected source:
2 unsigned int negativeunsigned() {
3     const unsigned int x = 4294967295; // OK
4     return x;
5 }

In the corrected source, a positive value was assigned to the unsigned result.

like image 40
Casey Avatar answered Oct 20 '22 07:10

Casey