aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2021-01-25 12:41:28 -0700
committerMartin Sebor <msebor@redhat.com>2021-01-25 12:41:28 -0700
commitd6f1cf644c45b76a27b6a6869dedaa030e3c7570 (patch)
tree099882d59ed8681df57417ddd194bc67af3039cf
parent7d54cccad332074d5fb81123796239f0f61b11a7 (diff)
downloadgcc-d6f1cf644c45b76a27b6a6869dedaa030e3c7570.zip
gcc-d6f1cf644c45b76a27b6a6869dedaa030e3c7570.tar.gz
gcc-d6f1cf644c45b76a27b6a6869dedaa030e3c7570.tar.bz2
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.
-rw-r--r--gcc/c-family/c-common.c2
-rw-r--r--gcc/cp/cvt.c9
-rw-r--r--gcc/testsuite/g++.dg/warn/Wnonnull10.C63
-rw-r--r--gcc/testsuite/g++.dg/warn/Wnonnull5.C10
-rw-r--r--gcc/testsuite/g++.dg/warn/Wnonnull9.C117
-rw-r--r--gcc/tree-ssa-ccp.c2
6 files changed, 195 insertions, 8 deletions
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 2028e93..813212c 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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",
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index f94488b..e809f0e 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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;
}
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull10.C b/gcc/testsuite/g++.dg/warn/Wnonnull10.C
new file mode 100644
index 0000000..a7e795c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull10.C
@@ -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" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull5.C b/gcc/testsuite/g++.dg/warn/Wnonnull5.C
index 78862d4..959cf18 100644
--- a/gcc/testsuite/g++.dg/warn/Wnonnull5.C
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull5.C
@@ -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)
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull9.C b/gcc/testsuite/g++.dg/warn/Wnonnull9.C
new file mode 100644
index 0000000..b6135c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull9.C
@@ -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" }
+}
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 965f092..3bfd4a6 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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",