On Wed, 23 Feb 2022, Jakub Jelinek wrote: > Hi! > > 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. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK. Thanks, Richard. > 2022-02-22 Jakub Jelinek <ja...@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. > > --- gcc/gimple-warn-recursion.cc.jj 2022-01-18 11:58:59.619981528 +0100 > +++ gcc/gimple-warn-recursion.cc 2022-02-22 13:19:43.592644576 +0100 > @@ -112,13 +112,25 @@ pass_warn_recursion::find_function_exit > 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; > + } > } > } > > --- gcc/testsuite/gcc.dg/Winfinite-recursion-3.c.jj 2022-02-22 > 13:28:10.345579876 +0100 > +++ gcc/testsuite/gcc.dg/Winfinite-recursion-3.c 2022-02-22 > 13:25:16.760999396 +0100 > @@ -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); > +} > --- gcc/testsuite/gcc.dg/Winfinite-recursion-4.c.jj 2022-02-22 > 13:28:13.604534458 +0100 > +++ gcc/testsuite/gcc.dg/Winfinite-recursion-4.c 2022-02-22 > 13:25:22.552918640 +0100 > @@ -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); > +} > --- gcc/testsuite/gcc.dg/Winfinite-recursion-5.c.jj 2022-02-22 > 13:28:16.690491449 +0100 > +++ gcc/testsuite/gcc.dg/Winfinite-recursion-5.c 2022-02-22 > 13:27:13.024378761 +0100 > @@ -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); > +} > > Jakub > > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)