MPS issue job004156

TitleMPS does not compile with GCC 8.3
Statusclosed
Priorityessential
Assigned userGareth Rees
OrganizationRavenbrook
DescriptionReported by Basile Starynkevitch [1]. Confirmed on platform xci6gc, with GCC 8.3.0:

    xci6gc: xci6gc/cool/format.o
    format.c: In function 'FormatDescribe':
    format.c:236:31: error: cast between incompatible function types from 'mps_fmt_scan_t' {aka 'int (*)(struct mps_ss_s *, void *, void *)'} to 'void * (*)(void)' [-Werror=cast-function-type]
                    " scan $F\n", (WriteFF)format->scan,
                                   ^
    format.c:237:31: error: cast between incompatible function types from 'mps_fmt_skip_t' {aka 'void * (*)(void *)'} to 'void * (*)(void)' [-Werror=cast-function-type]
                    " skip $F\n", (WriteFF)format->skip,
                                   ^
    format.c:238:31: error: cast between incompatible function types from 'mps_fmt_fwd_t' {aka 'void (*)(void *, void *)'} to 'void * (*)(void)' [-Werror=cast-function-type]
                    " move $F\n", (WriteFF)format->move,
                                   ^
    format.c:239:34: error: cast between incompatible function types from 'mps_fmt_isfwd_t' {aka 'void * (*)(void *)'} to 'void * (*)(void)' [-Werror=cast-function-type]
                    " isMoved $F\n", (WriteFF)format->isMoved,
                                      ^
    format.c:240:30: error: cast between incompatible function types from 'mps_fmt_pad_t' {aka 'void (*)(void *, long unsigned int)'} to 'void * (*)(void)' [-Werror=cast-function-type]
                    " pad $F\n", (WriteFF)format->pad,
                                  ^
AnalysisThe warning comes from -Wcast-function-type which is turned on by -Wextra [2].

We rely on our being able to pass any function pointer as an argument to WriteF, and on being able to retrieve that function pointer using va_arg. (See WriteF_firstformat_v in mpm.c.)

The C99 standard says at §6.3.2.3.8 that, "A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer."

So the cast is legitimate and GCC is just being annoying but I suppose we asked for that by turning on -Wextra.

Possible solutions:

1. Change the compiler options, e.g. -Wno-cast-function-type. This breaks support for customers who are compiling the MPS against their own code, as recommended in the manual.

2. Change (WriteFF) to (WriteFF)(void*). This is not defined by the C standard.

3. Drop the casts to (WriteFF). This introduces an assumption that any function pointer passed to a varargs function can be extracted by va_arg(args, WriteFF) which I think is not guaranteed by the standard, since §6.3.2.3.8 doesn't actually say that all function pointer types have the same size, just that they can be converted. It is also unsatisfactory because we lose the ability to automatically check the $F argument against the (WriteFF) cast.

4. Drop these values from the describe output altogether, thus avoiding the whole issue. Who uses these values anyway? It would normally be clear from context what they must be, and a user at the debugger prompt would be able to check them using the debugger's facilities.

5. Change the type of WriteFF to void (*)(void), since in GCC this "is special and matches everything, which can be used to suppress this warning".
How foundcustomer
Evidence[1] https://info.ravenbrook.com/mail/2019/03/13/09-11-43/0/
[2] https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
Created byGareth Rees
Created on2019-03-14 14:40:39
Last modified byGareth Rees
Last modified on2019-03-14 15:17:47
History2019-03-14 GDR Created.

Fixes

Change Effect Date User Description
196063 closed 2019-03-14 15:17:47 Gareth Rees Change the type of WriteFF to avoid compiler warnings from GCC 8.