aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2016-02-24 23:01:24 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2016-02-24 23:01:24 +0100
commit03ca8fb3da94f12e5cd2ba57373d3875cd8d8cf8 (patch)
treeaa66bb95b65b601ee8e6a8fef70163aacf5b9226
parent0b05329bbfaade628e97f5d33165f82337865153 (diff)
downloadgcc-03ca8fb3da94f12e5cd2ba57373d3875cd8d8cf8.zip
gcc-03ca8fb3da94f12e5cd2ba57373d3875cd8d8cf8.tar.gz
gcc-03ca8fb3da94f12e5cd2ba57373d3875cd8d8cf8.tar.bz2
re PR c++/69922 (Bogus -Wnonnull-compare for: ... ? static_cast<T*>(this) : nullptr)
PR c++/69922 * class.c (build_base_path): Set TREE_NO_WARNING on the null_test. Avoid folding it. * init.c (build_vec_delete_1, build_delete): Don't fold the non-NULL tests. * cp-gimplify.c (cp_fold): For TREE_NO_WARNING comparisons with NULL, unless they are folded into INTEGER_CST, error_mark_node or some comparison with NULL, avoid folding them and use either the original comparison or non-folded comparison of folded arguments. * cp-ubsan.c (cp_ubsan_instrument_vptr): Set TREE_NO_WARNING on the comparison, don't fold the comparison right away. * g++.dg/warn/Wnonnull-compare-6.C: New test. * g++.dg/warn/Wnonnull-compare-7.C: New test. * g++.dg/ubsan/pr69922.C: New test. From-SVN: r233684
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/class.c7
-rw-r--r--gcc/cp/cp-gimplify.c20
-rw-r--r--gcc/cp/cp-ubsan.c13
-rw-r--r--gcc/cp/init.c17
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/ubsan/pr69922.C18
-rw-r--r--gcc/testsuite/g++.dg/warn/Wnonnull-compare-6.C13
-rw-r--r--gcc/testsuite/g++.dg/warn/Wnonnull-compare-7.C19
9 files changed, 110 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 897c28f..28a3168 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+2016-02-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/69922
+ * class.c (build_base_path): Set TREE_NO_WARNING on the null_test.
+ Avoid folding it.
+ * init.c (build_vec_delete_1, build_delete): Don't fold the non-NULL
+ tests.
+ * cp-gimplify.c (cp_fold): For TREE_NO_WARNING comparisons with NULL,
+ unless they are folded into INTEGER_CST, error_mark_node or some
+ comparison with NULL, avoid folding them and use either the original
+ comparison or non-folded comparison of folded arguments.
+ * cp-ubsan.c (cp_ubsan_instrument_vptr): Set TREE_NO_WARNING on the
+ comparison, don't fold the comparison right away.
+
2016-02-24 Jason Merrill <jason@redhat.com>
PR c++/69323
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b705d6b..f6ad696 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -392,8 +392,11 @@ build_base_path (enum tree_code code,
if (null_test)
{
tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain);
- null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
- expr, zero);
+ null_test = build2_loc (input_location, NE_EXPR, boolean_type_node,
+ expr, zero);
+ /* This is a compiler generated comparison, don't emit
+ e.g. -Wnonnull-compare warning for it. */
+ TREE_NO_WARNING (null_test) = 1;
}
/* If this is a simple base reference, express it as a COMPONENT_REF. */
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index c59cd90..a77b242 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2069,8 +2069,24 @@ cp_fold (tree x)
x = fold (x);
if (TREE_NO_WARNING (org_x)
- && TREE_CODE (x) == TREE_CODE (org_x))
- TREE_NO_WARNING (x) = 1;
+ && warn_nonnull_compare
+ && COMPARISON_CLASS_P (org_x))
+ {
+ if (x == error_mark_node || TREE_CODE (x) == INTEGER_CST)
+ ;
+ else if (COMPARISON_CLASS_P (x))
+ TREE_NO_WARNING (x) = 1;
+ /* Otherwise give up on optimizing these, let GIMPLE folders
+ optimize those later on. */
+ else if (op0 != TREE_OPERAND (org_x, 0)
+ || op1 != TREE_OPERAND (org_x, 1))
+ {
+ x = build2_loc (loc, code, TREE_TYPE (org_x), op0, op1);
+ TREE_NO_WARNING (x) = 1;
+ }
+ else
+ x = org_x;
+ }
break;
case VEC_COND_EXPR:
diff --git a/gcc/cp/cp-ubsan.c b/gcc/cp/cp-ubsan.c
index 7454c0a..a5aefcf 100644
--- a/gcc/cp/cp-ubsan.c
+++ b/gcc/cp/cp-ubsan.c
@@ -70,10 +70,15 @@ cp_ubsan_instrument_vptr (location_t loc, tree op, tree type, bool is_addr,
vptr = fold_convert_loc (loc, pointer_sized_int_node, vptr);
vptr = fold_convert_loc (loc, uint64_type_node, vptr);
if (ckind == UBSAN_DOWNCAST_POINTER)
- vptr = fold_build3 (COND_EXPR, uint64_type_node,
- fold_build2 (NE_EXPR, boolean_type_node, op,
- build_zero_cst (TREE_TYPE (op))),
- vptr, build_int_cst (uint64_type_node, 0));
+ {
+ tree cond = build2_loc (loc, NE_EXPR, boolean_type_node, op,
+ build_zero_cst (TREE_TYPE (op)));
+ /* This is a compiler generated comparison, don't emit
+ e.g. -Wnonnull-compare warning for it. */
+ TREE_NO_WARNING (cond) = 1;
+ vptr = build3_loc (loc, COND_EXPR, uint64_type_node, cond,
+ vptr, build_int_cst (uint64_type_node, 0));
+ }
tree ti_decl = get_tinfo_decl (type);
mark_used (ti_decl);
tree ptype = build_pointer_type (type);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 19279e3..43f854c4 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3678,15 +3678,13 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
body = integer_zero_node;
/* Outermost wrapper: If pointer is null, punt. */
- tree cond
- = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, base,
- fold_convert (TREE_TYPE (base), nullptr_node));
+ tree cond = build2_loc (input_location, NE_EXPR, boolean_type_node, base,
+ fold_convert (TREE_TYPE (base), nullptr_node));
/* This is a compiler generated comparison, don't emit
e.g. -Wnonnull-compare warning for it. */
- if (TREE_CODE (cond) == NE_EXPR)
- TREE_NO_WARNING (cond) = 1;
- body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
- cond, body, integer_zero_node);
+ TREE_NO_WARNING (cond) = 1;
+ body = build3_loc (input_location, COND_EXPR, void_type_node,
+ cond, body, integer_zero_node);
body = build1 (NOP_EXPR, void_type_node, body);
if (controller)
@@ -4523,9 +4521,8 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
{
/* Handle deleting a null pointer. */
warning_sentinel s (warn_address);
- ifexp = fold (cp_build_binary_op (input_location,
- NE_EXPR, addr, nullptr_node,
- complain));
+ ifexp = cp_build_binary_op (input_location, NE_EXPR, addr,
+ nullptr_node, complain);
if (ifexp == error_mark_node)
return error_mark_node;
/* This is a compiler generated comparison, don't emit
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4ba14fc..e5cfd9a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2016-02-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/69922
+ * g++.dg/warn/Wnonnull-compare-6.C: New test.
+ * g++.dg/warn/Wnonnull-compare-7.C: New test.
+ * g++.dg/ubsan/pr69922.C: New test.
+
2016-02-24 Marek Polacek <polacek@redhat.com>
PR c/69819
diff --git a/gcc/testsuite/g++.dg/ubsan/pr69922.C b/gcc/testsuite/g++.dg/ubsan/pr69922.C
new file mode 100644
index 0000000..0392750
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ubsan/pr69922.C
@@ -0,0 +1,18 @@
+// PR c++/69922
+// { dg-do compile }
+// { dg-options "-fsanitize=vptr -Wnonnull-compare" }
+
+struct S { virtual ~S (); };
+struct T : S { T *bar (); T *baz (); T *q; bool b; };
+
+T *
+T::bar ()
+{
+ return static_cast<T*>(reinterpret_cast<S*>(this)); // { dg-bogus "nonnull argument" }
+}
+
+T *
+T::baz ()
+{
+ return static_cast<T*>(reinterpret_cast<S*>(b ? this : q)); // { dg-bogus "nonnull argument" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull-compare-6.C b/gcc/testsuite/g++.dg/warn/Wnonnull-compare-6.C
new file mode 100644
index 0000000..d327df9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull-compare-6.C
@@ -0,0 +1,13 @@
+// PR c++/69922
+// { dg-do compile }
+// { dg-options "-Wnonnull-compare" }
+
+struct T { virtual ~T (); };
+struct S { virtual ~S (); T *f (bool); };
+struct U : S, T {};
+
+T *
+S::f (bool b)
+{
+ return b ? static_cast<U *> (this) : (U *) 0; // { dg-bogus "nonnull argument" }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wnonnull-compare-7.C b/gcc/testsuite/g++.dg/warn/Wnonnull-compare-7.C
new file mode 100644
index 0000000..6c19a43
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wnonnull-compare-7.C
@@ -0,0 +1,19 @@
+// PR c++/69922
+// { dg-do compile }
+// { dg-options "-Wnonnull-compare" }
+
+struct S { virtual ~S (); };
+struct T { virtual ~T (); };
+bool b, c;
+S *p;
+T *q, *r;
+
+S::~S ()
+{
+ delete (b ? this : p); // { dg-bogus "nonnull argument" }
+}
+
+T::~T ()
+{
+ delete (b ? (c ? this : q) : r); // { dg-bogus "nonnull argument" }
+}