This patch fixes PR 57574, where a function defined (in C99 mode) as "inline" following a "static inline" declaration was wrongly considered an external reference, meaning (a) spurious diagnostics about references to static variables and (b) undefined references to the function could be generated as if it were non-static inline and an external definition had to be provided elsewhere. The fix is to detect this case in merge_decls and set DECL_EXTERNAL appropriately.
Bootstrapped with no regressions on x86_64-unknown-linux-gnu. Applied to mainline. c: 2013-11-29 Joseph Myers <jos...@codesourcery.com> PR c/57574 * c-decl.c (merge_decls): Clear DECL_EXTERNAL for a definition of an inline function following a static declaration. testsuite: 2013-11-29 Joseph Myers <jos...@codesourcery.com> PR c/57574 * gcc.dg/inline-35.c: New test. Index: gcc/testsuite/gcc.dg/inline-35.c =================================================================== --- gcc/testsuite/gcc.dg/inline-35.c (revision 0) +++ gcc/testsuite/gcc.dg/inline-35.c (revision 0) @@ -0,0 +1,19 @@ +/* A function definition of an inline function following a static + declaration does not make an inline definition in C99/C11 terms. + PR 57574. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -pedantic-errors" } */ + +static int n; + +static inline int f1 (void); +inline int f1 (void) { return n; } + +static int f2 (void); +inline int f2 (void) { return n; } + +static inline int f3 (void); +int f3 (void) { return n; } + +static int f4 (void); +int f4 (void) { return n; } Index: gcc/c/c-decl.c =================================================================== --- gcc/c/c-decl.c (revision 205497) +++ gcc/c/c-decl.c (working copy) @@ -2343,6 +2343,14 @@ merge_decls (tree newdecl, tree olddecl, tree newt && !current_function_decl) DECL_EXTERNAL (newdecl) = 0; + /* An inline definition following a static declaration is not + DECL_EXTERNAL. */ + if (new_is_definition + && (DECL_DECLARED_INLINE_P (newdecl) + || DECL_DECLARED_INLINE_P (olddecl)) + && !TREE_PUBLIC (olddecl)) + DECL_EXTERNAL (newdecl) = 0; + if (DECL_EXTERNAL (newdecl)) { TREE_STATIC (newdecl) = TREE_STATIC (olddecl); -- Joseph S. Myers jos...@codesourcery.com