]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix diagnostics for never-defined inline and nested functions (PR c/88720, PR c/88726).
authorJoseph Myers <joseph@codesourcery.com>
Wed, 16 Jan 2019 21:40:33 +0000 (21:40 +0000)
committerJoseph Myers <jsm28@gcc.gnu.org>
Wed, 16 Jan 2019 21:40:33 +0000 (21:40 +0000)
Bugs 88720 and 88726 report issues where a function is declared inline
in an inner scope, resulting in spurious diagnostics about it being
declared but never defined when that scope is left (possibly in some
cases also wrongly referring to the function as a nested function).
These are regressions that were introduced with the support for C99
inline semantics in 4.3 (they don't appear with 4.2; it's possible
some aspects of the bugs might have been introduced later than 4.3).

For the case of functions being wrongly referred to as nested,
DECL_EXTERNAL was not the right condition for a function being
non-nested; TREE_PUBLIC is appropriate for the case of non-nested
functions with external linkage, while !b->nested means this is the
outermost scope in which the function was declared and so avoids
catching the case of a file-scope static being redeclared inline
inside a function.

For the non-nested, external-linkage case, the code attempts to avoid
duplicate diagnostics by diagnosing only when scope != external_scope,
but actually scope == external_scope is more appropriate, as it's only
when the file and external scopes are popped that the code can
actually tell whether a function ended up being defined, and all such
functions will appear in the (GCC-internal) external scope.

Bootstrapped with no regressions on x86_64-pc-linux-gnu.

gcc/c:
Backport from mainline
2019-01-07  Joseph Myers  <joseph@codesourcery.com>

PR c/88720
PR c/88726
* c-decl.c (pop_scope): Use TREE_PUBLIC and b->nested to determine
whether a function is nested, not DECL_EXTERNAL.  Diagnose inline
functions declared but never defined only for external scope, not
for other scopes.

gcc/testsuite:
Backport from mainline
2019-01-07  Joseph Myers  <joseph@codesourcery.com>

PR c/88720
PR c/88726
* gcc.dg/inline-40.c, gcc.dg/inline-41.c: New tests.

From-SVN: r267987

gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/inline-40.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/inline-41.c [new file with mode: 0644]

index 86a4c9659736179828f6133d37aaf84be2034494..ab2eae1ff375a399fc2f426806b8f8df287738a2 100644 (file)
@@ -1,3 +1,15 @@
+2019-01-16  Joseph Myers  <joseph@codesourcery.com>
+
+       Backport from mainline
+       2019-01-07  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/88720
+       PR c/88726
+       * c-decl.c (pop_scope): Use TREE_PUBLIC and b->nested to determine
+       whether a function is nested, not DECL_EXTERNAL.  Diagnose inline
+       functions declared but never defined only for external scope, not
+       for other scopes.
+
 2018-01-02  Segher Boessenkool  <segher@kernel.crashing.org>
 
        Backport from trunk
index ed609d29f96b697b68a85b42e73807f4ec492b48..14a3832f7bf9c94bb0007a6ef533063a655d48f6 100644 (file)
@@ -1235,8 +1235,9 @@ pop_scope (void)
              && DECL_ABSTRACT_ORIGIN (p) != 0
              && DECL_ABSTRACT_ORIGIN (p) != p)
            TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
-         if (!DECL_EXTERNAL (p)
+         if (!TREE_PUBLIC (p)
              && !DECL_INITIAL (p)
+             && !b->nested
              && scope != file_scope
              && scope != external_scope)
            {
@@ -1252,7 +1253,7 @@ pop_scope (void)
                 in the same translation unit."  */
              if (!flag_gnu89_inline
                  && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (p))
-                 && scope != external_scope)
+                 && scope == external_scope)
                pedwarn (input_location, 0,
                         "inline function %q+D declared but never defined", p);
              DECL_EXTERNAL (p) = 1;
index af4e7a338a8be7026671108b0c28b037f8db7fa2..15a4270d9399921c4d4098bff3a4e9a56e4c36cf 100644 (file)
@@ -1,3 +1,12 @@
+2019-01-16  Joseph Myers  <joseph@codesourcery.com>
+
+       Backport from mainline
+       2019-01-07  Joseph Myers  <joseph@codesourcery.com>
+
+       PR c/88720
+       PR c/88726
+       * gcc.dg/inline-40.c, gcc.dg/inline-41.c: New tests.
+
 2019-01-16  Martin Jambor  <mjambor@suse.cz>
 
        Backported from mainline
diff --git a/gcc/testsuite/gcc.dg/inline-40.c b/gcc/testsuite/gcc.dg/inline-40.c
new file mode 100644 (file)
index 0000000..d0fdaee
--- /dev/null
@@ -0,0 +1,49 @@
+/* Test inline functions declared in inner scopes.  Bugs 88720 and 88726.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void
+inline_1 (void)
+{
+}
+
+void
+inline_2 (void)
+{
+}
+
+static void
+inline_static_1 (void)
+{
+}
+
+static void
+inline_static_2 (void)
+{
+}
+
+static void inline_static_3 (void);
+static void inline_static_4 (void);
+
+static void
+test (void)
+{
+  inline void inline_1 (void);
+  extern inline void inline_2 (void);
+  inline void inline_3 (void);
+  extern inline void inline_4 (void);
+  inline void inline_static_1 (void);
+  extern inline void inline_static_2 (void);
+  inline void inline_static_3 (void);
+  extern inline void inline_static_4 (void);
+}
+
+void
+inline_3 (void)
+{
+}
+
+void
+inline_4 (void)
+{
+}
diff --git a/gcc/testsuite/gcc.dg/inline-41.c b/gcc/testsuite/gcc.dg/inline-41.c
new file mode 100644 (file)
index 0000000..1511aee
--- /dev/null
@@ -0,0 +1,49 @@
+/* Test inline functions declared in inner scopes.  Bugs 88720 and 88726.  */
+/* { dg-do compile } */
+/* { dg-options "-fgnu89-inline" } */
+
+void
+inline_1 (void)
+{
+}
+
+void
+inline_2 (void)
+{
+}
+
+static void
+inline_static_1 (void)
+{
+}
+
+static void
+inline_static_2 (void)
+{
+}
+
+static void inline_static_3 (void);
+static void inline_static_4 (void);
+
+static void
+test (void)
+{
+  inline void inline_1 (void);
+  extern inline void inline_2 (void);
+  inline void inline_3 (void);
+  extern inline void inline_4 (void);
+  inline void inline_static_1 (void);
+  extern inline void inline_static_2 (void);
+  inline void inline_static_3 (void);
+  extern inline void inline_static_4 (void);
+}
+
+void
+inline_3 (void)
+{
+}
+
+void
+inline_4 (void)
+{
+}