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>