Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 5 Nov 2013 17:12:20 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Dimitry Andric <dim@FreeBSD.org>
Cc:        svn-src-head@FreeBSD.org, Sean Bruno <sbruno@FreeBSD.org>, src-committers@FreeBSD.org, svn-src-all@FreeBSD.org
Subject:   Re: svn commit: r257645 - head/gnu/lib/libgcc
Message-ID:  <20131105160307.U5956@besplex.bde.org>
In-Reply-To: <57710455-9B81-47FF-926B-1075EB6F4290@FreeBSD.org>
References:  <201311041815.rA4IFjwO081492@svn.freebsd.org> <57710455-9B81-47FF-926B-1075EB6F4290@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 4 Nov 2013, Dimitry Andric wrote:

> On 04 Nov 2013, at 19:15, Sean Bruno <sbruno@FreeBSD.org> wrote:
>> Author: sbruno
>> Date: Mon Nov  4 18:15:45 2013
>> New Revision: 257645
>> URL: http://svnweb.freebsd.org/changeset/base/257645
>>
>> Log:
>>  Quiesce warning around gcc_assert() for an inline macro that uses
>>  a static variable.  This code has been moved around in gcc, but is still in
>>  use in the latest trunk version of the compiler.
>>
>>  gnu/lib/libgcc/../../../contrib/gcc/unwind-dw2.c:208:36:
>>        warning: static variable 'dwarf_reg_size_table' is used in an inline
>>                 function with external linkage [-Wstatic-in-inline]
>>  gcc_assert (index < (int) sizeof(dwarf_reg_size_table));
>
> The warning is actually correct, since _Unwind_SetGR() is an extern
> inline function (although it is not explicitly declared as such), but it

extern has very confusing semantics, so it is hard to say what an extern
inline function is.  C99 broke this, so in C99 "extern inline" means the
definition (which must be turned into object code, giving a public function)
while plain "inline" means the declaration (which can be omitted from the
object code).  This is almost perfectly backwards relative to both normal
meanings of extern and relative to old gcc extern inline.  unwind-fw2.c
is clearly not C99 code, since it uses plain "inline" but needs the
public function(s).

> does access a static variable.  It would probably be safest to make the
> variable non-static instead, since the function itself cannot be changed
> to static inline.

This was probably not a bug with old gcc plain inline semantics, but
probably was a bug with old gcc extern inline semantics, since old
semantics weren't gratuitously strict but static variables just aren't
visible except in the file that has them combined with a plain inline
function (plain inline in old semantics = extern inline in new semantics).
unwind-dw2.c is an example of this working combination unless it is
broken by compiling it with new semantics.

It seems to take nonstandard warning flags and/or compiling for a
standard newer than the code to get this warning.  I get it mainly
with -std=c99 -pedantic, but there are many clearly broken cases.
My test program is:

     volatile static int x; inline int z(void) { return x; }

cc:  no warning; null object code
gcc: no warning; public function in object code

Already there is a huge incompatibility (bug in clang).  This is because
clang defaults to -std=c99 (or is it -std=clang99?) and thus gets new
C99 broken plain inline semantics, while gcc defaults to -std=gnu89
and thus gets old gnu89 less-broken plain inline semantics.

cc -std=c99:  no warning; null object code
gcc -std=c99: no warning; null object code

Now both get new inline semantics.  I don't see how the plain inline functions
in unwind-fw2.c can be public without either turning off new semantics or
turning on new semantics and declaring them as extern inline.  When the
example is modified to add a function that returns z(), z() is still not
made public.  This is new semantics.  z() should only be made public if
it is too large to inline and it is called by other functions in the file.
Even then, it probably needs to be renamed to avoid conflicts.

cc -std=gnu89:  no warning; public function in object code
gcc -std=gnu89: no warning; public function in object code

Correct.

cc -std=gnu89 -pedantic:     warning; public function in object code
gcc -std=gnu89 -pedantic: no warning; public function in object code

Bug in clang.  It emits the warning even for old semantics, although
it gives correct semantics.

cc -std=c99 -pedantic -fgnu89-inline:     warning; public function ...
gcc -std=c99 -pedantic -fgnu89-inline: no warning; public function ...

-fgnu89-inline works correctly to restores the inline semantics in
otherwise-c99 code, but it doesn't fix the warning.

Modifying the example to declare the function as "extern inline" gives
perfectly backwards behaviour.  E.g., with defaults it is now clang
that generates the public function and gcc not.

Compile-time flags like the unportable -Wno-static-in-inline, -std=force
and -fgnu89-inline are bad ways to modify this behaviour.  The semantic
changes should be limited to individual functions using attributes.
Another bug suite turns up when this is done:

     volatile static int x; __gnu89_inline int z(void) { return x; }

Someone broke the support for doing this correctly by removing
__gnu89_inline from <sys/cdefs.h> together with unportabalizing the code
that used it.  It now takes a hard-coded __attribute__(()) to do this.
I recovered the macro from FreeBSD[7-8] to fix the example:

#define	__gnu89_inline	__attribute__((__gnu_inline__)) __inline

(This preserves the design bug that __inline is part of the macro.
The related __always_inline macro only gives the attribute.)

This works right to the same extent as -fgnu-inline for modifying
-std=c99 -- it has limited scope, and is supported by clang, but doesn't
fix the warning.

Bruce



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