Menu ▾ ▴

#4139 C23 auto type inference omits initializer conversions and rejects valid declarations

closed-accepted
None
Front-end
5
7 hours ago
12 hours ago
No

1: Sample code that reproduces the problem.

void f(void)
{
  const int c = 1;
  auto x = c;
  ++x;
  (void)x;
}

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

sdcc -mz80 --std=c23 -S repro.c

(The same failure occurs with --std=c2y.)

3: SDCC version tested.

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/huc6280/f8/f8l TD- 4.6.4 #16998 (Linux)
published under GNU General Public License (GPL)

4: Observed and expected behaviour.

SDCC exits with status 1 and reports:

repro.c:5: error 33: Attempt to assign value to a constant variable (++)

The declaration of x is valid C23 and should infer int, permitting the increment. Its initializer undergoes lvalue conversion; the const qualification of c does not qualify the new object.

C23 draft N3096,
6.7.9 paragraph 2, specifies inference from the initializer type after
lvalue, array-to-pointer or function-to-pointer conversion:

The inferred type of the declared object is the type of the assignment expression after lvalue, array
to pointer or function to pointer conversion, additionally qualified by qualifiers and amended by attributes as they appear in the declaration specifiers, if any.
(The corresponding provision in N3886 is 6.7.10 paragraph 2.)

5: Additional checks and compiler comparison.

Compiler Explorer: SDCC trunk beside GCC 16.2.
Both panes contain the sample above. SDCC uses -mz80 --std=c23; GCC uses
-std=c23 -pedantic-errors -fsyntax-only. SDCC r16998 reports error 33;
GCC 16.2.0 accepts the source without diagnostics.

The local testing matrix comprises six related forms in both C23 and C2Y modes on all nine configurations below, with both local builds:

Initializer Expected inferred type Observed SDCC behaviour
const int object Unqualified int Increment rejected as const
volatile int object Unqualified int Type assertion on &x fails, warning 215
int array Pointer to int Errors 226 and 69
String literal Pointer after array conversion Errors 226/69; pointer increment also rejected
Function designator Function pointer Error 226
int *const object Modifiable pointer to int Increment rejected as const

The volatile case exits successfully, but _Static_assert(_Generic(&x, int *: 1, default: 0), "unqualified copy") fails. The other five examples exit unsuccessfully.

Configurations tested: Z80, STM8 default/large, MCS51 default/large/stack-auto, PDK14, S08 and Rabbit R2K. These are translation and type checks; no runtime test was performed for this discovery.

GCC 16.2.0 on Compiler Explorer accepts all eight retained sources without diagnostics using -std=c23 -pedantic-errors -fsyntax-only. This includes the six reported forms and two additional checks. The shared comparison link displays the minimal const-object example only.

Implementation observation: prepareDeclarationSymbol assigns the result of typeofOp(initializer) directly to both sym->type and sym->etype, without the conversions required for inference. For an array or function result, sym->etype also points to the first declarator rather than the final specifier.

Related

Bugs: #4140

Discussion

  • Christopher Bazley

    Christopher Bazley - 11 hours ago

    Please consider the attached candidate bug fix patch.

    The patch applies lvalue, array-to-pointer and function-to-pointer conversions before auto inference. It inspects a copy of the initializer because decoration can replace AST nodes, and sets etype to the final specifier of an inferred derived type. Explicit declaration qualifiers and pointed-to qualifiers remain.

    135 diagnostic checks passed: 15 cases on each of Z80, STM8 default/large, MCS51 default/large/stack-auto, PDK14, S08 and Rabbit R2K. The same tests without the proposed fix produced 18 diagnostic mismatches on each configuration. (This includes multiple
    unexpected diagnostics in individual cases; it is not a count of bugs.)

    The new tests cover const/volatile lvalue conversion, const pointer objects,
    arrays, string literals, direct function designators and function addresses, modifiable scalar literals, const aggregate copies, multidimensional arrays, absence of integer promotion and preservation of explicit const/volatile and const referenced types.

     
  • Maarten Brock

    Maarten Brock - 10 hours ago
    • status: open --> closed-accepted
    • assigned_to: Maarten Brock
     
  • Maarten Brock

    Maarten Brock - 10 hours ago

    Applied in [r16999].

     

    Related

    Commit: [r16999]

  • Maarten Brock

    Maarten Brock - 10 hours ago

    There is at least one remaining issue: the regression test generates this warning:

    cases/./../tests/bug-4139.c:48: warning 360: string literal assigned to pointer to non-const
    
     
    • Christopher Bazley

      Hi Maarten, thanks for accepting my patch. I think this one was important, so it's great to have it fixed.

      The warning is accurate but I do not believe that it indicates a flaw in the test. According to ISO C, the type of the array produced by a string literal is char [] and array-to-pointer conversion converts that to char *, which is therefore the type inferred from the initialiser "abc". Of course, SDCC can produce whatever diagnostic messages it chooses about whatever it pleases, so this is arguably not a bug even though it is strange.

       
      • Maarten Brock

        Maarten Brock - 7 hours ago

        The flaw in the test is that when you expect a warning from SDCC that cannot be resolved without sacrificing the test, it should be disabled with a pragma.

        The alternative could be to start a discussion about whether the warning should be marked pedantic or not on the developer mailing list. The regression tests run with the --less-pedantic flag.

        Long story short: regression tests should not produce warnings. The fact that they currently do is due to unresolved issues. At least that is my take on this.

         

Log in to post a comment.