Menu

#2497 typedef of function should be allowed - resolution of #2440 is too strict

open
Ben Shi
None
Front-end
4
2020-08-05
2016-04-24
Pavel Pisa
No

The typedef of function without pointer should be allowed as well as following use of function type with pointer symbol to declare pointer to the function variable or structure fields. Such use is directly mandated by examples in C99 standard

/* C99  6.7.7 Type definitions 7 EXAMPLE 4 */

typedef void fv(int), (*pfv)(int);
void (*signal(int, void (*)(int)))(int);
fv *signal(int, fv *);
pfv signal(int, pfv);
*/

But SDCC report some of these contructs as error after #2440 resolution

/* Following should be supported to not block reuse/porting of code */
typedef long fnc_t(int a, long b);
/* but SDCC reports test-func-typedef.c:11: error 220: type 'fnc_t' is function */

typedef long (*fnc_p_t)(int a, long b);

/* This seems to be supported by compilers but not sure if required by standard */
fnc_t fnc1, fnc2;

long fnc1(int a, long b)
{
  return 0;
}

fnc_t *fncp = &fnc1;

long test(void)
{
  long l = fncp(1, 2);
  fnc_p_t fp = fncp;

  return fp(l, 0);
}

Next are not necessarily correct and reporting them as error can help catch errors made by programmers even that some constructs are GCC accepted.

/* fnc_t fncp1 = &fnc1; error: function 'fncp1' is initialized like a variable */
/* fnc_t *fncp2 = fnc1; OK for GCC but not sure if according to C99 standard */

Same as original reported construct is error and should be reported.

typedef void test_func_t(void);
static test_func_t test_funcs[1];
/*  error: declaration of 'test_funcs' as array of functions */

But reporting as errors C99 valid constructs requires to adjust portable code specially for SDCC use and causes code less readable in some cases. It can be unacceptable for upstream projects and instead of accepting change it may be easier to drop SDCC support.

Please, consider to change parser to accept standard specified constructs.

Discussion

  • Ben Shi

    Ben Shi - 2016-04-25

    My opinion,

    (1) The following a.c should be accepted,

    // a.c
    typedef long fnc_t(int a, long b);
    typedef long (*fnc_p_t)(int a, long b);
    fnc_t fnc1;
    long fnc1(int a, long b)
    {
      return a + b + 0;
    }
    

    ~

    (2) The following c.c should be accepted,

    // c.c
    typedef long fnc_t(int a, long b);
    typedef long (*fnc_p_t)(int a, long b);
    
    long fnc1(int a, long b)
    {
      return a + b +0;
    }
    
    fnc_t *fncp1 = fnc1;
    fnc_p_t fncp2 = fnc1;
    
    long test(void)
    {
      long l0 = (*fncp1)(1, 2);
      long l1 = fncp2(1, 2);
      fnc_p_t fp = fncp1;
      return fp(l0, l1);
    }
    

    ~

    (3) The following e.c should be rejected,

    // e.c
    typedef long fnc_t(int a, long b);
    
    long fnc1(int a, long b)
    {
      return a + b + 0;
    }
    
    fnc_t fnc2 = fnc1;
    

    ~

    (4) The following f.c should be rejected,

    // f.c 
    typedef void test_func_t(void);
    static test_func_t test_funcs[1];
    

    ~

    (5) The following g.c should be accepted,

    // g.c
    typedef void (* test_func_t) (void);
    static test_func_t test_funcs[1];
    
     

    Last edit: Ben Shi 2016-04-25
  • Pavel Pisa

    Pavel Pisa - 2016-04-25

    I fully agree with that.

    fnc_t fnc1; is seldom used so it is not so big problem if it is not accepted. But others are quite common.

     
  • Ben Shi

    Ben Shi - 2016-04-28
    • status: open --> closed-fixed
    • assigned_to: Ben Shi
     
  • Ben Shi

    Ben Shi - 2016-04-28

    Fixed in [r9580].

     

    Last edit: Maarten Brock 2017-05-13
    • Bradley Jarvis

      Bradley Jarvis - 2017-05-10

      Hi Ben,
      Condition 1 'a.c' does not work in version 3.6.6. I get error 220, see my comment below. Please reopen this bug

       

      Last edit: Maarten Brock 2017-05-13
  • Bradley Jarvis

    Bradley Jarvis - 2016-08-31

    Hi,
    I use condition (1) 'a.c' to typedef module callback functions which are then used to declare a static function in main code but it no longer works even with the latest build 3.6.3 #9761. Unlike Pavel I think this feature is important and makes code easier to read and maintain

    ie.

    in module header:

    typedef void io_hardware_callback_t(io_hardware_event_t, unsigned short);

    in main code:

    // this used to work in 3.4.0 but not now >>> static io_hardware_callback_t hardware_callback;
    static void hardware_callback(io_hardware_event_t, unsigned short);

    uncommenting the above results in
    error 220: 'hardware_callback' has function type

    cheers Brad

     
  • Maarten Brock

    Maarten Brock - 2017-05-13
    • status: closed-fixed --> open
     

Log in to post a comment.