public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-7358] warn-recursion: Don't warn for __builtin_calls in gnu_inline extern inline functions [PR104633]
@ 2022-02-23 11:04 Jakub Jelinek
  0 siblings, 0 replies; only message in thread
From: Jakub Jelinek @ 2022-02-23 11:04 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:c8cb5098c7854a1ed07e85c6165ef0c348d6df1d

commit r12-7358-gc8cb5098c7854a1ed07e85c6165ef0c348d6df1d
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Wed Feb 23 12:03:55 2022 +0100

    warn-recursion: Don't warn for __builtin_calls in gnu_inline extern inline functions [PR104633]
    
    The first two testcases show different ways how e.g. the glibc
    _FORTIFY_SOURCE wrappers are implemented, and on Winfinite-recursion-3.c
    the new -Winfinite-recursion warning emits a false positive warning.
    
    It is a false positive because when a builtin with 2 names is called
    through the __builtin_ name (but not all builtins have a name prefixed
    exactly like that) from extern inline function with gnu_inline semantics,
    it doesn't mean the compiler will ever attempt to use the user inline
    wrapper for the call, the __builtin_ just does what the builtin function
    is expected to do and either expands into some compiler generated code,
    or if the compiler decides to emit a call it will use an actual definition
    of the function, but that is not the extern inline gnu_inline function
    which is never emitted out of line.
    Compared to that, in Winfinite-recursion-5.c the extern inline gnu_inline
    wrapper calls the builtin by the same name as the function's name and in
    that case it is infinite recursion, we actuall try to inline the recursive
    call and also error because the recursion is infinite during inlining;
    without always_inline we wouldn't error but it is still infinite recursion,
    the user has no control on how many recursive calls we actually inline.
    
    2022-02-22  Jakub Jelinek  <jakub@redhat.com>
    
            PR c/104633
            * gimple-warn-recursion.cc (pass_warn_recursion::find_function_exit):
            Don't warn about calls to corresponding builtin from extern inline
            gnu_inline wrappers.
    
            * gcc.dg/Winfinite-recursion-3.c: New test.
            * gcc.dg/Winfinite-recursion-4.c: New test.
            * gcc.dg/Winfinite-recursion-5.c: New test.

Diff:
---
 gcc/gimple-warn-recursion.cc                 | 22 +++++++++++++++++-----
 gcc/testsuite/gcc.dg/Winfinite-recursion-3.c | 18 ++++++++++++++++++
 gcc/testsuite/gcc.dg/Winfinite-recursion-4.c | 19 +++++++++++++++++++
 gcc/testsuite/gcc.dg/Winfinite-recursion-5.c | 18 ++++++++++++++++++
 4 files changed, 72 insertions(+), 5 deletions(-)

diff --git a/gcc/gimple-warn-recursion.cc b/gcc/gimple-warn-recursion.cc
index 3a50d5e3707..91a3cdbacd4 100644
--- a/gcc/gimple-warn-recursion.cc
+++ b/gcc/gimple-warn-recursion.cc
@@ -112,13 +112,25 @@ pass_warn_recursion::find_function_exit (basic_block bb)
 	  if (!strcmp (name, "siglongjmp"))
 	    return true;
 
-	  if (m_built_in && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
+	  if (m_built_in
+	      && gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)
 	      && m_built_in == DECL_FUNCTION_CODE (fndecl))
 	    {
-	      /* The call is being made from the definition of a built-in
-		 (e.g., in a replacement of one) to itself.  */
-	      m_calls->safe_push (stmt);
-	      return false;
+	      const char *cname
+		= IDENTIFIER_POINTER (DECL_NAME (current_function_decl));
+	      /* Don't warn about gnu_inline extern inline function
+		 like strcpy calling __builtin_strcpy, that is fine,
+		 if some call is made (the builtin isn't expanded inline),
+		 a call is made to the external definition.  */
+	      if (!(DECL_DECLARED_INLINE_P (current_function_decl)
+		    && DECL_EXTERNAL (current_function_decl))
+		  || strcmp (name, cname) == 0)
+		{
+		  /* The call is being made from the definition of a built-in
+		     (e.g., in a replacement of one) to itself.  */
+		  m_calls->safe_push (stmt);
+		  return false;
+		}
 	    }
 	}
 
diff --git a/gcc/testsuite/gcc.dg/Winfinite-recursion-3.c b/gcc/testsuite/gcc.dg/Winfinite-recursion-3.c
new file mode 100644
index 00000000000..9205422041e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Winfinite-recursion-3.c
@@ -0,0 +1,18 @@
+/* PR c/104633 */
+/* { dg-do compile } */
+/* { dg-options "-Winfinite-recursion" } */
+
+typedef __SIZE_TYPE__ size_t;
+int memcmp (const void *, const void *, size_t);
+
+extern inline __attribute__((always_inline, gnu_inline)) int
+memcmp (const void *p, const void *q, size_t size)	/* { dg-bogus "infinite recursion detected" } */
+{
+  return __builtin_memcmp (p, q, size);			/* { dg-bogus "recursive call" } */
+}
+
+int
+foo (const void *p, const void *q, size_t size)
+{
+  return memcmp (p, q, size);
+}
diff --git a/gcc/testsuite/gcc.dg/Winfinite-recursion-4.c b/gcc/testsuite/gcc.dg/Winfinite-recursion-4.c
new file mode 100644
index 00000000000..e9a2bb675d1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Winfinite-recursion-4.c
@@ -0,0 +1,19 @@
+/* PR c/104633 */
+/* { dg-do compile } */
+/* { dg-options "-Winfinite-recursion" } */
+
+typedef __SIZE_TYPE__ size_t;
+int memcmp (const void *, const void *, size_t);
+__typeof (memcmp) __memcmp_alias __asm ("memcmp");
+
+extern inline __attribute__((always_inline, gnu_inline)) int
+memcmp (const void *p, const void *q, size_t size)	/* { dg-bogus "infinite recursion detected" } */
+{
+  return __memcmp_alias (p, q, size);			/* { dg-bogus "recursive call" } */
+}
+
+int
+foo (const void *p, const void *q, size_t size)
+{
+  return memcmp (p, q, size);
+}
diff --git a/gcc/testsuite/gcc.dg/Winfinite-recursion-5.c b/gcc/testsuite/gcc.dg/Winfinite-recursion-5.c
new file mode 100644
index 00000000000..1c3d1b48f94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Winfinite-recursion-5.c
@@ -0,0 +1,18 @@
+/* PR c/104633 */
+/* { dg-do compile } */
+/* { dg-options "-Winfinite-recursion" } */
+
+typedef __SIZE_TYPE__ size_t;
+int memcmp (const void *, const void *, size_t);
+
+extern inline __attribute__((always_inline, gnu_inline)) int
+memcmp (const void *p, const void *q, size_t size)	/* { dg-warning "infinite recursion detected" } */
+{							/* { dg-error "inlining failed in call to" "" { target *-*-* } .-1 } */
+  return memcmp (p, q, size);				/* { dg-message "recursive call" } */
+}							/* { dg-message "called from here" "" { target *-*-* } .-1 } */
+
+int
+foo (const void *p, const void *q, size_t size)
+{
+  return memcmp (p, q, size);
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-02-23 11:04 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-23 11:04 [gcc r12-7358] warn-recursion: Don't warn for __builtin_calls in gnu_inline extern inline functions [PR104633] Jakub Jelinek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).