mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-15 14:01:04 +08:00
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:
parent
7d54cccad3
commit
d6f1cf644c
@ -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",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
63
gcc/testsuite/g++.dg/warn/Wnonnull10.C
Normal file
63
gcc/testsuite/g++.dg/warn/Wnonnull10.C
Normal 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" }
|
||||
}
|
@ -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)
|
||||
|
117
gcc/testsuite/g++.dg/warn/Wnonnull9.C
Normal file
117
gcc/testsuite/g++.dg/warn/Wnonnull9.C
Normal 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" }
|
||||
}
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user