PR c++/98646 - spurious -Wnonnull calling a member on the result of static_cast

gcc/c-family/ChangeLog:

	PR c++/98646
	* c-common.c (check_nonnull_arg): Adjust warning text.

gcc/cp/ChangeLog:

	PR c++/98646
	* cvt.c (cp_fold_convert): Propagate TREE_NO_WARNING.

gcc/ChangeLog:

	PR c++/98646
	* tree-ssa-ccp.c (pass_post_ipa_warn::execute): Adjust warning text.

gcc/testsuite/ChangeLog:

	PR c++/98646
	* g++.dg/warn/Wnonnull5.C: Adjust text of an expected warning.
	* g++.dg/warn/Wnonnull10.C: New test.
	* g++.dg/warn/Wnonnull9.C: New test.
This commit is contained in:
Martin Sebor 2021-01-25 12:41:28 -07:00
parent 7d54cccad3
commit d6f1cf644c
6 changed files with 195 additions and 8 deletions

View File

@ -5595,7 +5595,7 @@ check_nonnull_arg (void *ctx, tree param, unsigned HOST_WIDE_INT param_num)
if (param_num == 0)
{
warned = warning_at (loc, OPT_Wnonnull,
"%qs pointer null", "this");
"%qs pointer is null", "this");
if (warned && pctx->fndecl)
inform (DECL_SOURCE_LOCATION (pctx->fndecl),
"in a call to non-static member function %qD",

View File

@ -599,11 +599,14 @@ ignore_overflows (tree expr, tree orig)
}
/* Fold away simple conversions, but make sure TREE_OVERFLOW is set
properly. */
properly and propagate TREE_NO_WARNING if folding EXPR results
in the same expression code. */
tree
cp_fold_convert (tree type, tree expr)
{
bool nowarn = TREE_NO_WARNING (expr);
tree conv;
if (TREE_TYPE (expr) == type)
conv = expr;
@ -626,6 +629,10 @@ cp_fold_convert (tree type, tree expr)
conv = fold_convert (type, expr);
conv = ignore_overflows (conv, expr);
}
if (nowarn && TREE_CODE (expr) == TREE_CODE (conv))
TREE_NO_WARNING (conv) = nowarn;
return conv;
}

View File

@ -0,0 +1,63 @@
/* Very that -Wnonnull is issued for calls to inline member functions
with a null this pointer.
{ dg-do compile }
{ dg-options "-Wall" } */
#if __cplusplus < 201103L
# define nullptr 0
#endif
struct S
{
void f () { }
static void g () { }
virtual void h () { }
};
void f0 ()
{
static_cast<S*>(0)->f (); // { dg-warning "-Wnonnull" }
static_cast<S*>(0)->g ();
static_cast<S*>(0)->h (); // { dg-warning "-Wnonnull" }
}
void f1 ()
{
static_cast<S*>(nullptr)->f (); // { dg-warning "-Wnonnull" }
static_cast<S*>(nullptr)->g ();
static_cast<S*>(nullptr)->h (); // { dg-warning "-Wnonnull" }
}
void f2 ()
{
S* const p = 0;
p->f (); // { dg-warning "-Wnonnull" }
p->g ();
p->h (); // { dg-warning "-Wnonnull" }
}
#pragma GCC optimize "1"
void f3 ()
{
S *p = 0;
p->f (); // { dg-warning "-Wnonnull" }
p->g ();
p->h (); // { dg-warning "-Wnonnull" }
}
#pragma GCC optimize "2"
void f4 (S *p)
{
if (p)
return;
p->f (); // { dg-warning "-Wnonnull" }
p->g ();
p->h (); // { dg-warning "-Wnonnull" }
}

View File

@ -35,21 +35,21 @@ struct S
void warn_nullptr_this ()
{
((S*)nullptr)->f0 (""); // { dg-warning "3:'this' pointer null" "pr86568" { xfail *-*-* } }
// { dg-warning "this' pointer null" "pr86568 second variant" { target *-*-* } .-1 }
((S*)nullptr)->f0 (""); // { dg-warning "3:'this' pointer is null" "pr86568" { xfail *-*-* } }
// { dg-warning "this' pointer is null" "pr86568 second variant" { target *-*-* } .-1 }
}
void warn_null_this_cst ()
{
S* const null = 0;
null->f1 (""); // { dg-warning "3:'this' pointer null" }
null->f1 (""); // { dg-warning "3:'this' pointer is null" }
}
void warn_null_this_var ()
{
S* null = 0;
null->f2 (&null); // { dg-warning "3:'this' pointer null" "pr86568" { xfail *-*-* } }
// { dg-warning "'this' pointer null" "pr86568 second variant" { target *-*-* } .-1 }
null->f2 (&null); // { dg-warning "3:'this' pointer is null" "pr86568" { xfail *-*-* } }
// { dg-warning "'this' pointer is null" "pr86568 second variant" { target *-*-* } .-1 }
}
void warn_nullptr (S s)

View File

@ -0,0 +1,117 @@
/* PR c++/98646 - spurious -Wnonnull calling a member on the result
of static_cast
{ dg-do compile }
{ dg-options "-O2 -Wall" } */
struct A { virtual ~A (); };
struct B
{
virtual ~B ();
B* bptr ();
B& bref ();
};
struct C: A, B { virtual ~C (); void g () const; };
void c_cast_C_ptr (B *p)
{
((C*)p->bptr ())->g ();
}
void c_cast_const_C_ptr (B *p)
{
((const C*)p->bptr ())->g ();
}
void static_cast_C_ptr (B *p)
{
static_cast<C*>(p->bptr ())->g ();
}
void static_cast_const_C_ptr (B *p)
{
/* The static_cast can't fail so verify that no warning is issued
here, even though GCC emits a null check for its argument. */
static_cast<const C*>(p->bptr ())->g (); // { dg-bogus "\\\[-Wnonnull" }
}
void dynamic_cast_C_ptr (B *p)
{
// The dynamic_cast might fail so a warning is justified.
dynamic_cast<C*>(p->bptr ())->g (); // { dg-warning "\\\[-Wnonnull" }
}
void dynamic_cast_const_C_ptr (B *p)
{
dynamic_cast<const C*>(p->bptr ())->g (); // { dg-warning "\\\[-Wnonnull" }
}
void c_cast_C_ref (B *p)
{
((C&)p->bref ()).g ();
}
void c_cast_const_C_ref (B *p)
{
((const C&)p->bref ()).g ();
}
void static_cast_C_ref (B *p)
{
static_cast<C&>(p->bref ()).g ();
}
void static_cast_const_C_ref (B *p)
{
static_cast<const C&>(p->bref ()).g ();
}
void dynamic_cast_C_ref (B *p)
{
/* The dynamic_cast fails by throwing an exception so verify that
no warning is issued. */
dynamic_cast<C&>(p->bref ()).g ();
}
void dynamic_cast_const_C_ref (B *p)
{
dynamic_cast<const C&>(p->bref ()).g ();
}
struct D: B, A { virtual ~D (); void g () const; };
void c_cast_D_ptr (B *p)
{
((D*)p->bptr ())->g ();
}
void c_cast_const_D_ptr (B *p)
{
((const D*)p->bptr ())->g ();
}
void static_cast_D_ptr (B *p)
{
static_cast<D*>(p->bptr ())->g ();
}
void static_cast_const_D_ptr (B *p)
{
/* The static_cast can't fail so verify that no warning is issued
here, even though GCC emits a null check for its argument. */
static_cast<const D*>(p->bptr ())->g (); // { dg-bogus "\\\[-Wnonnull" }
}
void dynamic_cast_D_ptr (B *p)
{
// The dynamic_cast might fail so a warning is justified.
dynamic_cast<D*>(p->bptr ())->g (); // { dg-warning "\\\[-Wnonnull" }
}
void dynamic_cast_const_D_ptr (B *p)
{
dynamic_cast<const D*>(p->bptr ())->g (); // { dg-warning "\\\[-Wnonnull" }
}

View File

@ -3564,7 +3564,7 @@ pass_post_ipa_warn::execute (function *fun)
if (argno == 0)
{
if (warning_at (loc, OPT_Wnonnull,
"%G%qs pointer null", stmt, "this")
"%G%qs pointer is null", stmt, "this")
&& fndecl)
inform (DECL_SOURCE_LOCATION (fndecl),
"in a call to non-static member function %qD",