diff options
author | Jakub Jelinek <jakub@redhat.com> | 2022-02-23 12:03:55 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2022-02-23 12:03:55 +0100 |
commit | c8cb5098c7854a1ed07e85c6165ef0c348d6df1d (patch) | |
tree | 68479c8aa737f8ac5c32c6dc1deef31b7d608ce5 /gcc/gimple-warn-recursion.cc | |
parent | 06770148711226ba243b964451dfa8816d5d23e5 (diff) | |
download | gcc-c8cb5098c7854a1ed07e85c6165ef0c348d6df1d.zip gcc-c8cb5098c7854a1ed07e85c6165ef0c348d6df1d.tar.gz gcc-c8cb5098c7854a1ed07e85c6165ef0c348d6df1d.tar.bz2 |
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.
Diffstat (limited to 'gcc/gimple-warn-recursion.cc')
-rw-r--r-- | gcc/gimple-warn-recursion.cc | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/gcc/gimple-warn-recursion.cc b/gcc/gimple-warn-recursion.cc index 3a50d5e..91a3cdb 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; + } } } |