C prohibits this (6.7.4#3): extern inline int f(void) { static int n; return ++n; } Even with 'gnu89' extern-inline semantics, gcc does not treat this predictably, as a given call site may use one of two possible instances of 'n', so a warning to that effect would be useful.
Confirmed with mainline (20030718). I certainly can't get any warnings with the various -W* options.
remember GNU "extern inline" == c99 inline while GNU "inline" == C99 "extern inline".
[6.7.4#3] An inline definition of a function with external linkage shall not contain a definition of a modifiable object with static storage duration, and shall not contain a reference to an identifier with internal linkage. The following is an excerpt from bug report 16622: ** File 5 //the following 3 function definitions would all violate 6.7.4#3 // inline void f1_bad() {static a;} //violates part a static x1; // inline void f2_bad() {extern x1;} //violates part b // inline void f3_bad() {x1 = 0;} //violates part b //but the following are OK extern inline void f() {static a; extern x1; x1=0;} //not inline def static inline void g() {static a; extern x1; x1=0;} //not external linkage static [void] h(void); static inline [void] h() {static a; extern x1; x1=0;} //neither i.d. nor e.l. ** //comment: [void] is where 'void' should have gone in original 16622#4 message but didn't (a typo/omission). There are other 'void' accidently missing from earlier parts of the original (not shown in above quote). [The 'g' example under section 2 (and also the last paragraph under section 2) may be of interest here, but I won't quote it.]
I have a patch for this at <http://gcc.gnu.org/ml/gcc-patches/2006-05/msg00182.html> which is on hold for 4.3.
Subject: Bug 11377 Author: geoffk Date: Wed Nov 1 04:47:30 2006 New Revision: 118356 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118356 Log: * c-decl.c (grokdeclarator): Don't set DECL_EXTERNAL on inline static functions in c99 mode. PR 16622 * doc/extend.texi (Inline): Update. * c-tree.h (struct language_function): Remove field 'extern_inline'. * c-decl.c (current_extern_inline): Delete. (pop_scope): Adjust test for an undefined nested function. Add warning about undeclared inline function. (diagnose_mismatched_decls): Update comments. Disallow overriding of inline functions in a translation unit in C99. Allow inline declarations in C99 at any time. (merge_decls): Boolize variables. Handle C99 'extern inline' semantics. (grokdeclarator): Set DECL_EXTERNAL here for functions. Handle C99 inline semantics. (start_function): Don't clear current_extern_inline. Don't set DECL_EXTERNAL. (c_push_function_context): Don't push current_extern_inline. (c_pop_function_context): Don't restore current_extern_inline. PR 11377 * c-typeck.c (build_external_ref): Warn about static variables used in extern inline functions. * c-decl.c (start_decl): Warn about static variables declared in extern inline functions. Added: trunk/gcc/testsuite/gcc.dg/inline-13.c trunk/gcc/testsuite/gcc.dg/inline-14.c trunk/gcc/testsuite/gcc.dg/inline-15.c trunk/gcc/testsuite/gcc.dg/inline-16.c trunk/gcc/testsuite/gcc.dg/inline6.c trunk/gcc/testsuite/gcc.dg/inline7.c Modified: trunk/gcc/ChangeLog trunk/gcc/c-decl.c trunk/gcc/c-tree.h trunk/gcc/c-typeck.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.dg/inline-10.c
Subject: Bug 11377 Author: geoffk Date: Wed Nov 1 04:48:15 2006 New Revision: 118357 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=118357 Log: * c-decl.c (grokdeclarator): Don't set DECL_EXTERNAL on inline static functions in c99 mode. PR 16622 * doc/extend.texi (Inline): Update. * c-tree.h (struct language_function): Remove field 'extern_inline'. * c-decl.c (current_extern_inline): Delete. (pop_scope): Adjust test for an undefined nested function. Add warning about undeclared inline function. (diagnose_mismatched_decls): Update comments. Disallow overriding of inline functions in a translation unit in C99. Allow inline declarations in C99 at any time. (merge_decls): Boolize variables. Handle C99 'extern inline' semantics. (grokdeclarator): Set DECL_EXTERNAL here for functions. Handle C99 inline semantics. (start_function): Don't clear current_extern_inline. Don't set DECL_EXTERNAL. (c_push_function_context): Don't push current_extern_inline. (c_pop_function_context): Don't restore current_extern_inline. PR 11377 * c-typeck.c (build_external_ref): Warn about static variables used in extern inline functions. * c-decl.c (start_decl): Warn about static variables declared in extern inline functions. Modified: trunk/gcc/doc/extend.texi
This should now be fixed.