Menu ▾ ▴

#4093 Overflow in an integer constant expression is accepted without a diagnostic

open
nobody
None
other
5
4 days ago
2026-09-28
No

1: Sample code that reproduces the problem.

#ifdef __SDCC
#define TEST_INT_MAX 32767
#else
#include <limits.h>
#define TEST_INT_MAX INT_MAX
#endif

enum { unrepresentable_int = TEST_INT_MAX + 1 }; /* ERROR */

2: Exact command used to run SDCC on this sample code

./bin/sdcc -c bug.c

3: SDCC version tested

Git f68fca8a4368ece9fe93b21f2e0341282b104359, SDCC 4.6.3 #0 (Linux).

Affected in valdiag testing on mcs51, mcs51-large, mcs51-stack-auto, ds390, z80, z180, r2k, r4k, sm83, tlcs90, hc08, s08, mos6502, huc6280, stm8, f8, pdk13, pdk14, and pdk15.

4: Copy of the error message or incorrect output, or a clear description of the observed versus expected behavior.

N3886 6.6.1p20 says that each constant expression shall evaluate to a constant that is in the range of representable values for its type. According to the ISO C standard, all constraint violations must be diagnosed. SDCC, for which int has a maximum value of 32767 on the tested ports, accepts this expression without a diagnostic and folds it as if signed integer arithmetic had wrapped. The conditional definition makes the same test use the host implementation's INT_MAX with the comparison compilers.

GCC 13.3.0 and Clang 18.1.3 diagnose the overflow. TCC 0.9.28rc (mob 9db1105, 2026-09-26) accepts it without a diagnostic and therefore has the same bug.

Related

Bugs: #4119
Bugs: #4127

Discussion

  • Christopher Bazley

    Attaching a candidate patch to fix this bug.

    This is one of eight independent patches against SDCC commit
    c8cee3a5b4656a3d7ef97ef6078c38a016a02cfb (2026-09-28).
    The patches were also applied together to the baseline commit and built with the PIC14 and PIC16 ports disabled. The full device library build completed successfully. Focused valdiag testing of the eight new files passed on all 19 valdiag targets: 27 checks per target, zero failures.

    make -C support/regression -j2 test-ucz80:

    0 failures, 36745 tests, 6409 test cases
    
     

    Last edit: Christopher Bazley 2026-09-29
    • Philipp Klaus Krause

      This doesn't look wrong at first sight (though I didn't check very closely yet), but I the patch looks like it only fixes the missing diagnostic for signed int, but not for unsigned int, long, etc despite the language in N3886 6.6.1p20 apparently also requiring a diagnostic for those.

      P.S.: I don't see anything about _BitInt in valPlus, is that a problem (but if it is, it is probably outside the scope of this ticket)?

       
      • Christopher Bazley

        Hi Philipp, thanks for reviewing the patch. I agree that the fix is very incomplete. I have a patch that tries to fix all cases of overflow for constant integer expressions, but it is rather big and complicated. Instead of attaching that, I have split it into separate bug reports that will require separate bug fixes.

         
        • Christopher Bazley

          Please see bug [#4100], [#4101] and [#4102]. I think those are preconditions for fixing this bug properly.

           

          Related

          Bugs: #4100
          Bugs: #4101
          Bugs: #4102


          Last edit: Maarten Brock 2026-10-04
      • Christopher Bazley

        Hi Philipp,

        Please find a revised candidate patch attached. The original patch only added an overflow check for signed int addition. This replacement broadens that coverage and applies directly to r16984.

        Regarding _BitInt, the revised patch checks the computed result type before the int, long and shared long long/_BitInt branches, using bitsForType for the actual width. Tests cover signed _BitInt overflow at 2, 17 and 64 bits and preserve unsigned wrapping.

        The changes are:

        1. Use one overflow-checking helper for signed addition, subtraction, multiplication, division, remainder, unary negation and left shift. It checks the computed result type, covering int, long, long long and signed _BitInt, rather than assuming the result is int. The tests include promotions and mixed types where the operation is valid in the resulting type.

        2. Check before performing the invalid arithmetic. The original patch computed the result first and checked whether narrowing changed it. That approach cannot safely handle the widest signed type, because the calculation itself may overflow on the host. The replacement uses unsigned arithmetic for the boundary checks, emits warning 165 and returns zero with the computed type for error recovery. That also avoids a second diagnostic caused by converting an invalid result.

        3. Suppress the overflow warning in unevaluated operands: sizeof, typeof, typeof_unqual, the controlling expression of _Generic, short-circuited logical operands and unselected conditional branches. Evaluated branches still warn.

        4. Leave valid unsigned wrapping unchanged. The fixes for [#4100], [#4101] and [#4102] are now upstream, so this patch does not include them. It preserves the existing unsigned multiplication warning. Conditional-branch suppression uses the same truth test as the [#4101] fix, with tests for wide integer and fractional conditions.

        5. Expand bug-4093.c from four test groups to 35, covering overflow, valid boundaries, unsigned wrapping and unevaluated operands. The overflow examples use initialisers rather than enum declarations to isolate arithmetic diagnostics from enum-specific constraints.

        The complete valdiag suite passed across 8 configurations. A focused run with SDCCval.c and SDCCast.c instrumented by undefined behaviour sanitiser also passed all 280 test-group runs without errors. Three existing regression files compiled on six targets and completed successfully on Z80. The full runtime regression suite was not run yet.

         

        Related

        Bugs: #4100
        Bugs: #4101
        Bugs: #4102

        • Christopher Bazley

          Sorry, I need to rework the patch again. There are many existing cases of overflow where it is unacceptable to implement anything other than wrapping behaviour.

           
          • Christopher Bazley

            Hi @spth

            Please consider the attached revised version of the candidate bugfix.

            Compared to the previous candidate patch:

            • Overflow now produces a warning without replacing the result with zero. Folding retains the wrapped target result, including when warning 165 is disabled.
            • Host arithmetic is safer: negating signed min is handled explicitly, and signed 64-bit addition/subtraction avoid host overflow and out-of-range unsigned-to-signed casts.
            • Division and remainder now build on the merged fix for [#4119] by adding diagnostics before the existing error-recovery path, preserving the recovered values.
            • Tests now check results as well as diagnostics.
            • Rebased this version of the patch on r16993, with updated ChangeLog context.
             

            Related

            Bugs: #4119

  • Christopher Bazley

    I think the fix for this bug should depend on the fix for [#4119], as well as all of its previous dependencies.

     

    Related

    Bugs: #4119


Log in to post a comment.