Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Mar 2017 13:27:27 -0800
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        Bruce Evans <brde@optusnet.com.au>
Cc:        Andriy Gapon <avg@freebsd.org>, src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   Re: svn commit: r314862 - head/sys/modules/qlxgbe
Message-ID:  <20170309212727.GT1044@FreeBSD.org>
In-Reply-To: <20170309203335.M1817@besplex.bde.org>
References:  <201703071543.v27FhnoL024242@repo.freebsd.org> <20170307221733.GN1044@FreeBSD.org> <70fcdcf4-cfa5-2382-ea60-55ac1a91e06b@FreeBSD.org> <20170308193709.Q2738@besplex.bde.org> <20170308215056.GP1044@FreeBSD.org> <20170309203335.M1817@besplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
  Bruce,

On Thu, Mar 09, 2017 at 10:51:17PM +1100, Bruce Evans wrote:
B> > Bruce, I am sorry, I can't resist from asking that in a straight unpolite way:
B> >
B> > Unportable to what? Back to XX century?
B> 
B> Unportable to all versions of standard C up to and including at least
B> C11.  Unportable by programmers who don't know what is standard.  I
B> don't know much about C11, but just looked this up.  It has something
B> like gnu89 anonymous struct/unions but not ms extensions.  clang takes
B> more than -fms-extensions to support ms extensions, so the kernel can't
B> be using any beyond gnu89 ones and -fms-extensions in CFLAGS is part
B> of another suite of errors.  The kernel uses -std=iso9899:1999 but
B> userland uses the correct -std=gnu99.  -std=iso9899:1999 should disallow
B> gnu89 anonymous struct/unions, but it only works for gcc.  There must
B> be almost no code in the kernel using anonymous struct/unions, not
B> "not a lot" since the misconfigured -std disallows it for C99 compilers.
B>    (It is strange that use of anonymous struct/unions didn't grow in the
B>    1990's).  CFLAGS in FreeBSD is almost readable and portable.  It
B>    doesn't have -std.  So the standard defaults to gnu89 or gnu99.
B>    Userland got this wrong for a while by setting -std to c99 when
B>    it first used -std, but now uses gnu99.)
B> 
B> Documentation for anonymous struct/unions is hard to find.  clang has
B> nalmost no documentation in FreeBSD, and gnu documentation was last
B> installed where I can find it easily in FreeBSD-9.  The latter seemed
B> to have nothing about anonymous struct/unions, but I finally found a
B> pointer to it in gcc.info when I looked up -fms-extensions.  Gnu
B> spells "anonymous struct/unions" as unnamed fields and has adequate
B> documentation under the latter.
B> 
B> For gcc, -fs-extensions is documented to do bad things like turning
B> off the warning for "implicit int", so it is not the default.  It
B> enablesenables the following extensions to gcc anonymous unnamed fields:
B> - anonymous struct/unions can have a tag
B> - the tag on anonymous struct/unions is actually useful (it can be used
B>    in following definitions)
B> - somthing related with a typedef name instead of a tag name.
B> 
B> Contrary to the log message for r278913, clang doesn't do the right thing
B> here without any extra options.  Rather the reverse.  clang fails to
B> detect an error.  gcc detects the error, and r278913 prevents gcc
B> detecting the error.
B> 
B> I couldn't find any flags to make clang support ms extensions for
B> unnamed fileds (it accepts -fms-extensions but still gives warnings
B> and errors for unnamed fields).  But the kernel apparently only uses
B> old gnu unnamed fields.  The kernel is compiled with the wrong flags
B> -std=iso9899:1999.  This should turn off all extensions of C99.  It
B> turns off old gnu unnamed fields for gcc but not for clang.  Userland
B> is compiled with the correct flags -std=gnu99.  r278913 adds
B> -fms-extensions instead of fixing -std.
B> 
B> Example:
B> 
B> X struct bar2 { int i; };
B> X 
B> X struct foo {
B> X 	struct bar { int i; };
B> X 	struct bar2;
B> X 	struct bar b1;
B> X 	struct bar2 b2;
B> X } f;
B> 
B> clang with no flags, clang -std=c99, clang -std=gnu99 and clang -std=c11
B> compile this with 2 warnings (that the 2 anoymous structs don't declare
B> anything).  Adding -f-ms-extensions changes the 2 anonymous structs
B> to declare ms extensions but still warns about them, and gives a
B> redefinition error for i in struct bar (says it redefines i in struct
B> bar2).
B> 
B> gcc-4.2.1 does everything as correctly as possible (it cannot support c11).
B> Without -fms-extensions, it gives the same warnings as clang.  With
B> -fms-extensions, it just works.
B> 
B> In this example, the use of ms extensions doesn't do much.  It just allows
B> declaring b1 without repeating the definition of an anonymous struct bar.
B> This would be useful if struct bar were much larger.
B> 
B> The other fields are to demonstrate access names and inadertently expose
B> bugs in clang.  'i' in the first struct bar can be accessed as f.i.  The
B> other i's reqire more verbose access names.  Actually, the first in the
B> struct and the 'i' in it can't be named, since 'struct bar2;' is anonymous
B> so the only possible name for the 'i' in it is f.i, but that conflicts with
B> f.i for the first struct bar.  clang considers this to be an error.  But
B> I think gcc is correct in allowing it.  The first struct bar2 can work as
B> padding, and this might be useful (like anonymost bit-fields for padding).
B> 
B> b1 demonstrates the use of the ms extension.  There is no problem with
B> its access names, since both b1 and b1.i are named and b1 in b1.i
B> prevents conflicts, but f.b1.i is not as conveniently named as f.i.
B> 
B> b2 demonstrates normal use of struct declared in outer scope, and the
B> anonymous use of struct bar was supposed to demonstrate that the outer
B> declaration works for anonymous fields too.  It might work if there
B> is no name conflict (remove the first anonymous field for that).  Then
B> we can reference the 'i' in it with the short access name f.i.  Otherwise,
B> it just doesn't work for clang, and gives not very useful behaviour of
B> only padding or bugs for gcc (f.i could be any of the anonymous i's;
B> if it is always the first one, the the behaviour is unmbiguous but
B> using it is an obfuscation).
B> 
B> Second example:
B> 
B> X struct foo {
B> X 	struct { int i; };
B> X 	struct { int j; };
B> X } f;
B> 
B> This just simple old gnu and not so old C11 features in a simple way.
B> This should require -std=gnuN (N >= 89) or std=c11 to compile.  It can
B> also be compiled by std=cN (N >= 89) plus -fms-extensions.  gcc with
B> plain -std=cN (89 <= N <= 99) attempts to be a C99 compiler and rejects
B> it.  clang with plain -std=cN (89 <= N <= 99) doesn't attempt to be a
B> C99 compiler and accepts it.  clang with -std=cN (89 <= N <= 99) plus
B> -pedantic gives the most useful messages.  The messages are still only
B> warnings, but give the reason for rejection (that anonymous struct are
B> a new (C11) feature).

Bruce, the very first sentence of your mail says "Unportable to all versions
of standard C up to and including at least C11".

The very last one says "... (that anonymous struct are a new (C11) feature)".

So, looks like closer to the end of your mail you agreed that this is standard
feature of C. Of C11, if you wish.

I find it a really nice feature, and other developers also do, so why shouldn't
we make use of it?

You'd say that it will make code unportable to C99 and C89. The next question
is: why should it be portable? Any compiler, that has had a new release within
last 5 years, supports this features.

-- 
Totus tuus, Glebius.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20170309212727.GT1044>