Menu ▾ ▴

#4218 Casts to function types are accepted without a diagnostic

open
nobody
None
Front-end
5
1 day ago
2 days ago
No

1: Sample code that reproduces the problem.

typedef int F(void);
void f(int (*p)(void))
{
  (F)p;
}

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

sdcc -mz80 --std=c2y --nostdinc -S bug.c -o bug.asm

3: SDCC version tested.

SDCC 4.6.4 #17068 (Linux), tested 23 October 2026.

4: Observed and expected behaviour.

SDCC exits successfully and emits no diagnostic.

N3886 6.5.5 paragraph 2 requires a cast type name to specify a scalar type unless it specifies void. F is a function type, not a pointer type, so this cast violates the constraint. The valid pointer cast is (F *)p.

Reference: N3886.

5: Additional checks.

Both int-returning and void-returning function type variants are silently accepted on Z80, MCS51, STM8, PDK14 and MOS65C02 in C99/C11/C23/C2Y: 40 invalid checks. The function-pointer cast and a cast to void compile silently. Casts to structure, union and array types are already rejected with error 36.

GCC 13.3.0 with -std=c2x -pedantic-errors -fsyntax-only rejects the invalid cases. GCC 16.2 and Clang were not tested.

Discussion

  • Christopher Bazley

    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -22,7 +22,7 @@
    
     SDCC exits successfully and emits no diagnostic.
    
    -N3886 6.5.5 paragraph 2 requires a cast type name to specify a scalar type unless it specifies void. F is a function type, not a pointer type, so this cast violates the constraint. The valid pointer cast is `(F *)p`.
    +N3886 6.5.5 paragraph 2 requires a cast type name to specify a scalar type unless it specifies `void`. `F` is a function type, not a pointer type, so this cast violates the constraint. The valid pointer cast is `(F *)p`.
    
     Reference: [N3886](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3886.pdf).
    
     
  • Maarten Brock

    Maarten Brock - 1 day ago

    But aren't functions already pointers in themselves?
    This is allowed, right?

    int foo(void);
    int (*p)(void) = foo;
    

    It is not necessary to use &foo here, though allowed as well.

     
    • Christopher Bazley

      But aren't functions already pointers in themselves?

      Function designators 'decay' to function pointers, and the () operator requires an operand of function pointer type, but that does not in itself imply that functions are pointers.
      They are treated like pointers in certain contexts, just like arrays are treated like pointers to their first element in certain contexts, but that does not imply that casting to an array type is equivalent to casting to the type of a pointer to the array's elements.

      typedef int Foo_t(float);
      Foo_t foo;
      int main(void)
      {
          Foo_t *f = (Foo_t)foo; // accepted by SDCC but not GCC or Clang
          return 0;
      }
      

      See https://godbolt.org/z/xjvWhhGn8

       

Log in to post a comment.