On Mon, May 26, 2014 at 9:01 PM, Patrick Palka <[email protected]> wrote:
> Hi,
>
> This patch teaches the C++ frontend to warn on NULL checks against
> inline functions and it teaches the middle-end to fold NULL checks
> against inline functions. These two things are currently done for
> non-inline C++ functions, but inline functions are exceptional in that
> the C++ frontend marks them as weak, and NULL checks against weak
> symbols cannot be folded in general because the symbol may be mapped to
> NULL at link-time.
>
> But in the case of an inline function, the fact that it's a weak symbol
> is an implementation detail. And because it is not permitted to
> explicitly give an inline function the "weak" attribute (see
> handle_weak_attribute), in order to acheive $SUBJECT it suffices to
> assume that all inline functions are non-null, which is what this patch
> does.
>
> Bootstrap and regtest against x86_64-unknown-linux-gnu in progress. Is
> this patch OK assuming no regressions?
What about always_inline function wrappers as used in FORTIFY_SOURCE?
IIRC the actual referenced function may be declared weak and thus the
address can compare to NULL? Sth like
extern void __foo (void) __attribute__((weak,asm("foo")));
extern inline __attribute__((always_inline,gnu_inline)) void foo (void)
{
__foo ();
}
int main()
{
if (foo == 0)
return 0;
abort ();
}
The issue is that the inline and alias may be hidden to the user and thus
he'll get unwanted and confusing warnings.
Richard.
> 2014-05-26 Patrick Palka <[email protected]>
>
> * c-family/c-common.c (decl_with_nonnull_addr_p): Assume inline
> functions are non-null.
> * fold-const.c (tree_single_nonzero_warnv_p): Likewise.
> ---
> gcc/c-family/c-common.c | 4 +++-
> gcc/fold-const.c | 5 ++++-
> gcc/testsuite/g++.dg/inline-1.C | 14 ++++++++++++++
> 3 files changed, 21 insertions(+), 2 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/inline-1.C
>
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index 6ec14fc..d4747a0 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -4508,7 +4508,9 @@ decl_with_nonnull_addr_p (const_tree expr)
> return (DECL_P (expr)
> && (TREE_CODE (expr) == PARM_DECL
> || TREE_CODE (expr) == LABEL_DECL
> - || !DECL_WEAK (expr)));
> + || !DECL_WEAK (expr)
> + || (TREE_CODE (expr) == FUNCTION_DECL
> + && DECL_DECLARED_INLINE_P (expr))));
> }
>
> /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
> diff --git a/gcc/fold-const.c b/gcc/fold-const.c
> index 188b179..2796079 100644
> --- a/gcc/fold-const.c
> +++ b/gcc/fold-const.c
> @@ -16052,7 +16052,10 @@ tree_single_nonzero_warnv_p (tree t, bool
> *strict_overflow_p)
> || (DECL_CONTEXT (base)
> && TREE_CODE (DECL_CONTEXT (base)) == FUNCTION_DECL
> && auto_var_in_fn_p (base, DECL_CONTEXT (base)))))
> - return !VAR_OR_FUNCTION_DECL_P (base) || !DECL_WEAK (base);
> + return !VAR_OR_FUNCTION_DECL_P (base)
> + || !DECL_WEAK (base)
> + || (TREE_CODE (base) == FUNCTION_DECL
> + && DECL_DECLARED_INLINE_P (base));
>
> /* Constants are never weak. */
> if (CONSTANT_CLASS_P (base))
> diff --git a/gcc/testsuite/g++.dg/inline-1.C b/gcc/testsuite/g++.dg/inline-1.C
> new file mode 100644
> index 0000000..65beff1
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/inline-1.C
> @@ -0,0 +1,14 @@
> +// { dg-options "-Waddress" }
> +
> +inline void
> +foo (void)
> +{
> +}
> +
> +int
> +bar (void)
> +{
> + return foo == 0; // { dg-warning "never be NULL" }
> +}
> +
> +// { dg-final { scan-assembler-not "foo" } }
> --
> 2.0.0.rc2
>