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

Reply via email to