mbox series

[RFC,0/3] tweaks for QEMU's C standard

Message ID 20180810171102.16451-1-alex.bennee@linaro.org
Headers show
Series tweaks for QEMU's C standard | expand

Message

Alex Bennée Aug. 10, 2018, 5:10 p.m. UTC
Hi,

While I was reviewing Richard's SVE series I found Travis choking on
some perfectly valid c99. It turns out that Travis default image is
old enough that gcc defaults to -std=gnu89 hence the problem. However
switching to c99 isn't enough as we use GNUisms and even gnu99 still
trips up on qemu-secomp.

Of course we could just jump to C11 already?

This is an RFC because this could descend into a C standards
bike-shedding exercise but I thought I'd at least put it out there on
a Friday afternoon ;-)

Alex Bennée (3):
  HACKING: mention the C GNU extensions we use
  qemu-seccomp: manually expand SCMP_A1
  .travis.yml: ensure we support C99 on old compilers

 .travis.yml    | 2 +-
 HACKING        | 5 +++++
 qemu-seccomp.c | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

Comments

Daniel P. Berrangé Aug. 13, 2018, 9:07 a.m. UTC | #1
On Fri, Aug 10, 2018 at 06:10:58PM +0100, Alex Bennée wrote:
> Hi,
> 
> While I was reviewing Richard's SVE series I found Travis choking on
> some perfectly valid c99. It turns out that Travis default image is
> old enough that gcc defaults to -std=gnu89 hence the problem. However
> switching to c99 isn't enough as we use GNUisms and even gnu99 still
> trips up on qemu-secomp.
> 
> Of course we could just jump to C11 already?

We've always required GCC or a compatible compiler (CLang is only viable
alternative option really). We use a number of GCC extensions to the C
standard and I don't see a compelling reason to stop using them.

From that POV I think we do *NOT* need to care about official C standards
(c89, c99, c11, etc), only the GNU C standards (gnu89, gnu99, gnu11, etc).

> This is an RFC because this could descend into a C standards
> bike-shedding exercise but I thought I'd at least put it out there on
> a Friday afternoon ;-)

I did some archeology to inform our plans...

The default GCC C standards across various versions are:

  8.2.1: gnu17
  7.3.1: gnu11
  6.4.1: gnu11
  5.3.1: gnu11
  4.9.1: gnu89
  4.4.7: gnu89

Interesting to note that no version of GCC ever defaulted to gnu99. It was
not fully implemented initially and by the time the standard was fully
implemented, gnu11 was already good enough to be the default. So GCC jumped
straight from gnu89 as default to gnu11 as default.

Across the various distros we aim to support we have:

      RHEL-7: 4.8.5
      Debian (Stretch): 6.3.0
      Debian (Jessie): 4.9.2
      OpenBSD (Ports): 4.9.4
      FreeBSD (Ports): 8.2.0
      OpenSUSE Leap 15: 7.3.1
      SLE12-SP2:
      Ubuntu (Xenial): 5.4.0
      macOS (Homebrew): 8.2.0

IOW plenty of our plaforms are still on 4.x which defaults to gnu89.

In GCC 4.x, gnu99 is said to be incomplete (but usable) and gnu11
are said to be incomplete and experimental (ie don't use it).

The lowest common denominator supported by all our platforms is thus
gnu89.

If we don't mind that gnu99 is not fully complete in 4.x, we could use
that standard.

We definitely can't use gnu11 any time soon.

Given that many modern platforms default to gnu11, I think we should
set an explicit -std=gnu89, or -std=gnu99, because otherwise we risk
accidentally introducing code that relies on gnu11 features.

Regards,
Daniel
Daniel P. Berrangé Aug. 13, 2018, 9:18 a.m. UTC | #2
On Mon, Aug 13, 2018 at 10:07:05AM +0100, Daniel P. Berrangé wrote:
> On Fri, Aug 10, 2018 at 06:10:58PM +0100, Alex Bennée wrote:
> > Hi,
> > 
> > While I was reviewing Richard's SVE series I found Travis choking on
> > some perfectly valid c99. It turns out that Travis default image is
> > old enough that gcc defaults to -std=gnu89 hence the problem. However
> > switching to c99 isn't enough as we use GNUisms and even gnu99 still
> > trips up on qemu-secomp.
> > 
> > Of course we could just jump to C11 already?
> 
> We've always required GCC or a compatible compiler (CLang is only viable
> alternative option really). We use a number of GCC extensions to the C
> standard and I don't see a compelling reason to stop using them.
> 
> From that POV I think we do *NOT* need to care about official C standards
> (c89, c99, c11, etc), only the GNU C standards (gnu89, gnu99, gnu11, etc).
> 
> > This is an RFC because this could descend into a C standards
> > bike-shedding exercise but I thought I'd at least put it out there on
> > a Friday afternoon ;-)
> 
> I did some archeology to inform our plans...
> 
> The default GCC C standards across various versions are:
> 
>   8.2.1: gnu17
>   7.3.1: gnu11
>   6.4.1: gnu11
>   5.3.1: gnu11
>   4.9.1: gnu89
>   4.4.7: gnu89
> 
> Interesting to note that no version of GCC ever defaulted to gnu99. It was
> not fully implemented initially and by the time the standard was fully
> implemented, gnu11 was already good enough to be the default. So GCC jumped
> straight from gnu89 as default to gnu11 as default.
> 
> Across the various distros we aim to support we have:
> 
>       RHEL-7: 4.8.5
>       Debian (Stretch): 6.3.0
>       Debian (Jessie): 4.9.2
>       OpenBSD (Ports): 4.9.4
>       FreeBSD (Ports): 8.2.0
>       OpenSUSE Leap 15: 7.3.1
>       SLE12-SP2:
>       Ubuntu (Xenial): 5.4.0
>       macOS (Homebrew): 8.2.0
> 
> IOW plenty of our plaforms are still on 4.x which defaults to gnu89.
> 
> In GCC 4.x, gnu99 is said to be incomplete (but usable) and gnu11
> are said to be incomplete and experimental (ie don't use it).
> 
> The lowest common denominator supported by all our platforms is thus
> gnu89.
> 
> If we don't mind that gnu99 is not fully complete in 4.x, we could use
> that standard.
> 
> We definitely can't use gnu11 any time soon.
> 
> Given that many modern platforms default to gnu11, I think we should
> set an explicit -std=gnu89, or -std=gnu99, because otherwise we risk
> accidentally introducing code that relies on gnu11 features.

Also, we should ensure the min required GCC version via biuld time
check of some kind. eg something like

#if !(__GNUC_PREREQ(4, 4) || defined(__clang__))
# error "QEMU requires GCC >= 4.4, or CLang"
#endif


We can even check the C standard at build time if desired. eg I see
these symbols defined for various -std=xxx args:

 gnu89: #undef __STDC_VERSION__
 gnu99: #define __STDC_VERSION__ 199901
 gnu11: #define __STDC_VERSION__ 201112L
 gnu17: #define __STDC_VERSION__ 201710L


(See  "gcc -std=XXX  -dM -E - < /dev/null")

Regards,
Daniel
Thomas Huth Aug. 13, 2018, 9:25 a.m. UTC | #3
On 08/13/2018 11:07 AM, Daniel P. Berrangé wrote:
> On Fri, Aug 10, 2018 at 06:10:58PM +0100, Alex Bennée wrote:
>> Hi,
>>
>> While I was reviewing Richard's SVE series I found Travis choking on
>> some perfectly valid c99. It turns out that Travis default image is
>> old enough that gcc defaults to -std=gnu89 hence the problem. However
>> switching to c99 isn't enough as we use GNUisms and even gnu99 still
>> trips up on qemu-secomp.
>>
>> Of course we could just jump to C11 already?
> 
> We've always required GCC or a compatible compiler (CLang is only viable
> alternative option really). We use a number of GCC extensions to the C
> standard and I don't see a compelling reason to stop using them.
> 
> From that POV I think we do *NOT* need to care about official C standards
> (c89, c99, c11, etc), only the GNU C standards (gnu89, gnu99, gnu11, etc).
> 
>> This is an RFC because this could descend into a C standards
>> bike-shedding exercise but I thought I'd at least put it out there on
>> a Friday afternoon ;-)
> 
> I did some archeology to inform our plans...
> 
> The default GCC C standards across various versions are:
> 
>   8.2.1: gnu17
>   7.3.1: gnu11
>   6.4.1: gnu11
>   5.3.1: gnu11
>   4.9.1: gnu89
>   4.4.7: gnu89
> 
> Interesting to note that no version of GCC ever defaulted to gnu99. It was
> not fully implemented initially and by the time the standard was fully
> implemented, gnu11 was already good enough to be the default. So GCC jumped
> straight from gnu89 as default to gnu11 as default.
> 
> Across the various distros we aim to support we have:
> 
>       RHEL-7: 4.8.5
>       Debian (Stretch): 6.3.0
>       Debian (Jessie): 4.9.2
>       OpenBSD (Ports): 4.9.4
>       FreeBSD (Ports): 8.2.0
>       OpenSUSE Leap 15: 7.3.1
>       SLE12-SP2:
>       Ubuntu (Xenial): 5.4.0
>       macOS (Homebrew): 8.2.0
> 
> IOW plenty of our plaforms are still on 4.x which defaults to gnu89.

Thanks for the great summary!

> In GCC 4.x, gnu99 is said to be incomplete (but usable) and gnu11
> are said to be incomplete and experimental (ie don't use it).
> 
> The lowest common denominator supported by all our platforms is thus
> gnu89.
> 
> If we don't mind that gnu99 is not fully complete in 4.x, we could use
> that standard.
> 
> We definitely can't use gnu11 any time soon.
> 
> Given that many modern platforms default to gnu11, I think we should
> set an explicit -std=gnu89, or -std=gnu99, because otherwise we risk
> accidentally introducing code that relies on gnu11 features.

Sounds good. What about trying -std=gnu99 first, and if we run into
problems, switch back to -std=gnu89 later?

 Thomas
Peter Maydell Aug. 13, 2018, 9:29 a.m. UTC | #4
On 13 August 2018 at 10:18, Daniel P. Berrangé <berrange@redhat.com> wrote:
> Also, we should ensure the min required GCC version via biuld time
> check of some kind. eg something like
>
> #if !(__GNUC_PREREQ(4, 4) || defined(__clang__))
> # error "QEMU requires GCC >= 4.4, or CLang"
> #endif

Our current minimum is 4.1, I think (per commit fa54abb8c298f),
though we could bump that if there's utility in doing so.

Overall I think we should prefer to avoid specific gcc
version checks wherever we can. clang supports a useful
set of tests like __has_feature and __has_attribute;
gcc supports some of these (eg __has_attribute from gcc 5).

Random aside: I just stumbled across a comment in configure
about a workaround for a gcc 4.6.x bug which says "We should
be able to delete this at the end of 2013" :-)

thanks
-- PMM
Alex Bennée Aug. 13, 2018, 9:52 a.m. UTC | #5
Daniel P. Berrangé <berrange@redhat.com> writes:

> On Mon, Aug 13, 2018 at 10:07:05AM +0100, Daniel P. Berrangé wrote:
>> On Fri, Aug 10, 2018 at 06:10:58PM +0100, Alex Bennée wrote:
>> > Hi,
>> >
>> > While I was reviewing Richard's SVE series I found Travis choking on
>> > some perfectly valid c99. It turns out that Travis default image is
>> > old enough that gcc defaults to -std=gnu89 hence the problem. However
>> > switching to c99 isn't enough as we use GNUisms and even gnu99 still
>> > trips up on qemu-secomp.
>> >
>> > Of course we could just jump to C11 already?
>>
>> We've always required GCC or a compatible compiler (CLang is only viable
>> alternative option really). We use a number of GCC extensions to the C
>> standard and I don't see a compelling reason to stop using them.
>>
>> From that POV I think we do *NOT* need to care about official C standards
>> (c89, c99, c11, etc), only the GNU C standards (gnu89, gnu99, gnu11, etc).
>>
>> > This is an RFC because this could descend into a C standards
>> > bike-shedding exercise but I thought I'd at least put it out there on
>> > a Friday afternoon ;-)
>>
>> I did some archeology to inform our plans...
>>
>> The default GCC C standards across various versions are:
>>
>>   8.2.1: gnu17
>>   7.3.1: gnu11
>>   6.4.1: gnu11
>>   5.3.1: gnu11
>>   4.9.1: gnu89
>>   4.4.7: gnu89
>>
>> Interesting to note that no version of GCC ever defaulted to gnu99. It was
>> not fully implemented initially and by the time the standard was fully
>> implemented, gnu11 was already good enough to be the default. So GCC jumped
>> straight from gnu89 as default to gnu11 as default.
>>
>> Across the various distros we aim to support we have:
>>
>>       RHEL-7: 4.8.5
>>       Debian (Stretch): 6.3.0
>>       Debian (Jessie): 4.9.2
>>       OpenBSD (Ports): 4.9.4
>>       FreeBSD (Ports): 8.2.0
>>       OpenSUSE Leap 15: 7.3.1
>>       SLE12-SP2:
>>       Ubuntu (Xenial): 5.4.0
>>       macOS (Homebrew): 8.2.0
>>
>> IOW plenty of our plaforms are still on 4.x which defaults to gnu89.
>>
>> In GCC 4.x, gnu99 is said to be incomplete (but usable) and gnu11
>> are said to be incomplete and experimental (ie don't use it).
>>
>> The lowest common denominator supported by all our platforms is thus
>> gnu89.
>>
>> If we don't mind that gnu99 is not fully complete in 4.x, we could use
>> that standard.

Thanks for the digging. I wonder what is missing in 4.x?

As far as I can tell we make heavy use of typeof() but I don't know how
to audit for other GNUisms? Everything should be in a compiler.h right?

I just noticed we have a C11-like generics macro in there ;-)

>>
>> We definitely can't use gnu11 any time soon.
>>
>> Given that many modern platforms default to gnu11, I think we should
>> set an explicit -std=gnu89, or -std=gnu99, because otherwise we risk
>> accidentally introducing code that relies on gnu11 features.
>
> Also, we should ensure the min required GCC version via biuld time
> check of some kind. eg something like
>
> #if !(__GNUC_PREREQ(4, 4) || defined(__clang__))
> # error "QEMU requires GCC >= 4.4, or CLang"
> #endif
>
>
> We can even check the C standard at build time if desired. eg I see
> these symbols defined for various -std=xxx args:
>
>  gnu89: #undef __STDC_VERSION__
>  gnu99: #define __STDC_VERSION__ 199901
>  gnu11: #define __STDC_VERSION__ 201112L
>  gnu17: #define __STDC_VERSION__ 201710L
>
>
> (See  "gcc -std=XXX  -dM -E - < /dev/null")
>
> Regards,
> Daniel


--
Alex Bennée
Daniel P. Berrangé Aug. 13, 2018, 11:03 a.m. UTC | #6
On Mon, Aug 13, 2018 at 11:25:49AM +0200, Thomas Huth wrote:
> On 08/13/2018 11:07 AM, Daniel P. Berrangé wrote:
> > On Fri, Aug 10, 2018 at 06:10:58PM +0100, Alex Bennée wrote:
> >> Hi,
> >>
> >> While I was reviewing Richard's SVE series I found Travis choking on
> >> some perfectly valid c99. It turns out that Travis default image is
> >> old enough that gcc defaults to -std=gnu89 hence the problem. However
> >> switching to c99 isn't enough as we use GNUisms and even gnu99 still
> >> trips up on qemu-secomp.
> >>
> >> Of course we could just jump to C11 already?
> > 
> > We've always required GCC or a compatible compiler (CLang is only viable
> > alternative option really). We use a number of GCC extensions to the C
> > standard and I don't see a compelling reason to stop using them.
> > 
> > From that POV I think we do *NOT* need to care about official C standards
> > (c89, c99, c11, etc), only the GNU C standards (gnu89, gnu99, gnu11, etc).
> > 
> >> This is an RFC because this could descend into a C standards
> >> bike-shedding exercise but I thought I'd at least put it out there on
> >> a Friday afternoon ;-)
> > 
> > I did some archeology to inform our plans...
> > 
> > The default GCC C standards across various versions are:
> > 
> >   8.2.1: gnu17
> >   7.3.1: gnu11
> >   6.4.1: gnu11
> >   5.3.1: gnu11
> >   4.9.1: gnu89
> >   4.4.7: gnu89
> > 
> > Interesting to note that no version of GCC ever defaulted to gnu99. It was
> > not fully implemented initially and by the time the standard was fully
> > implemented, gnu11 was already good enough to be the default. So GCC jumped
> > straight from gnu89 as default to gnu11 as default.
> > 
> > Across the various distros we aim to support we have:
> > 
> >       RHEL-7: 4.8.5
> >       Debian (Stretch): 6.3.0
> >       Debian (Jessie): 4.9.2
> >       OpenBSD (Ports): 4.9.4
> >       FreeBSD (Ports): 8.2.0
> >       OpenSUSE Leap 15: 7.3.1
> >       SLE12-SP2:
> >       Ubuntu (Xenial): 5.4.0
> >       macOS (Homebrew): 8.2.0
> > 
> > IOW plenty of our plaforms are still on 4.x which defaults to gnu89.
> 
> Thanks for the great summary!
> 
> > In GCC 4.x, gnu99 is said to be incomplete (but usable) and gnu11
> > are said to be incomplete and experimental (ie don't use it).
> > 
> > The lowest common denominator supported by all our platforms is thus
> > gnu89.
> > 
> > If we don't mind that gnu99 is not fully complete in 4.x, we could use
> > that standard.
> > 
> > We definitely can't use gnu11 any time soon.
> > 
> > Given that many modern platforms default to gnu11, I think we should
> > set an explicit -std=gnu89, or -std=gnu99, because otherwise we risk
> > accidentally introducing code that relies on gnu11 features.
> 
> Sounds good. What about trying -std=gnu99 first, and if we run into
> problems, switch back to -std=gnu89 later?

I don't have a strong opinion either way - both options would be better
than what we do today by relying on the variable gcc built-in defaults.

Using -std=gnu99 gives slightly weaker protection in that we might still
accidentally use features which are not supported in the limitd gnu99
impl of gcc 4.x. I think that's unlikely, however, hence I don't really
mind either of gnu89 or gnu99

Regards,
Daniel