Menu

#3954 Mismatch in generic selection when array-to-pointer decay expected

open
nobody
None
Front-end
5
5 days ago
2026-03-23
No

1: Sample code that reproduces the problem.

void foo (const char (*pacc)[64])
{
  const char acc[64];
  static_assert (_Generic (acc, const char *: 1, default: 0)); // passes
  static_assert (_Generic (*pacc, const char *: 1, default: 0)); // fails
}

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

sdcc --std=c23 -c /work/bug3.c

3: SDCC version tested (type "sdcc -v" to find it)

SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/r4k/r5k/r6k/sm83/tlcs90/ez80/z80n/r800/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502/mos65c02/f8/f8l TD- 4.5.21 #16327 (Linux)

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

In 6.5.2.1 "Generic selection", C23 says:

The type of the
controlling expression is the type of the expression as if it had undergone an lvalue conversion,
array to pointer conversion, or function to pointer conversion

See https://www.open-std.org/JTC1/SC22/WG14/www/docs/n3220.pdf

When the controlling expression in a generic selection has an array type, the result of array-to-pointer decay is not always the expected type. It seems to depend on the form of the controlling expression; not only its type, as it should.

SDCC produces the following (wrong) diagnostic message, but no diagnostic message about the preceding statement:

/work/bug3.c:5: warning 246: static assertion failed

Neither statement should also result in a "static assertion failed" warning because the type of acc and *pacc should be the same.

Discussion

  • Benedikt Freisen

    Notes:

    This variant of the second static_assert apparently works

      static_assert (_Generic (pacc, const char (*)[64]: 1, default: 0));
    

    and so does this one (C2y),

      static_assert (_Generic (typeof (*pacc), const char [64]: 1, default: 0));
    

    but this one fails, too:

      static_assert (_Generic (*pacc, const char [64]: 1, default: 0));
    

    I suspect that something goes wrong either in case '*': in decorateType in SDCCast.c, or in aggregateToPointer in SDCCsymt.c.

     
  • Benedikt Freisen

    With --stack-auto, this one works, too.

    Quoting myself:

    The observed behavior can potentially be explained with SDCC's default settings:

    For historical reasons, the default target -mmcs51 generates non-reeantrant function code, unless --stack-auto is specified. It then compares qualified function types, because it must not ignore (explicit or implicit) address space qualifiers. See also [feature-requests:#948], which addresses this unintuitiveness.

     

    Related

    Feature Requests: #948

    • Christopher Bazley

      With --stack-auto, this one works, too.

      Thanks for the tip. I can add that to all of my makefiles and in Compiler Explorer (when I remember). As a user, it's not clear why non-reentrant code should entail any change to the treatment of 'const', 'volatile' or '_Optional' qualifiers though.

      I imagine that the machine-specific lowering of a function with signature

      void foo (__pdata char (*paqc)[64])
      

      is exactly that same as the machine-specific lowering of a function with signature

      void foo (__pdata char *pqc)
      

      Isn't it? If so, I'd expect the type of the expression *paqc to be the same as the type of pqc after undergoing array to pointer decay, even in the presence of address space qualifiers.

       

Log in to post a comment.

MongoDB Logo MongoDB