Commit 03ca8fb3 by Jakub Jelinek Committed by Jakub Jelinek

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
parent 0b05329b
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> 2016-02-24 Jason Merrill <jason@redhat.com>
PR c++/69323 PR c++/69323
......
...@@ -392,8 +392,11 @@ build_base_path (enum tree_code code, ...@@ -392,8 +392,11 @@ build_base_path (enum tree_code code,
if (null_test) if (null_test)
{ {
tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain); tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain);
null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, null_test = build2_loc (input_location, NE_EXPR, boolean_type_node,
expr, zero); 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. */ /* If this is a simple base reference, express it as a COMPONENT_REF. */
......
...@@ -2069,8 +2069,24 @@ cp_fold (tree x) ...@@ -2069,8 +2069,24 @@ cp_fold (tree x)
x = fold (x); x = fold (x);
if (TREE_NO_WARNING (org_x) if (TREE_NO_WARNING (org_x)
&& TREE_CODE (x) == TREE_CODE (org_x)) && warn_nonnull_compare
TREE_NO_WARNING (x) = 1; && 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; break;
case VEC_COND_EXPR: case VEC_COND_EXPR:
......
...@@ -70,10 +70,15 @@ cp_ubsan_instrument_vptr (location_t loc, tree op, tree type, bool is_addr, ...@@ -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, pointer_sized_int_node, vptr);
vptr = fold_convert_loc (loc, uint64_type_node, vptr); vptr = fold_convert_loc (loc, uint64_type_node, vptr);
if (ckind == UBSAN_DOWNCAST_POINTER) if (ckind == UBSAN_DOWNCAST_POINTER)
vptr = fold_build3 (COND_EXPR, uint64_type_node, {
fold_build2 (NE_EXPR, boolean_type_node, op, tree cond = build2_loc (loc, NE_EXPR, boolean_type_node, op,
build_zero_cst (TREE_TYPE (op))), build_zero_cst (TREE_TYPE (op)));
vptr, build_int_cst (uint64_type_node, 0)); /* 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); tree ti_decl = get_tinfo_decl (type);
mark_used (ti_decl); mark_used (ti_decl);
tree ptype = build_pointer_type (type); tree ptype = build_pointer_type (type);
......
...@@ -3678,15 +3678,13 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, ...@@ -3678,15 +3678,13 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
body = integer_zero_node; body = integer_zero_node;
/* Outermost wrapper: If pointer is null, punt. */ /* Outermost wrapper: If pointer is null, punt. */
tree cond tree cond = build2_loc (input_location, NE_EXPR, boolean_type_node, base,
= fold_build2_loc (input_location, NE_EXPR, boolean_type_node, base, fold_convert (TREE_TYPE (base), nullptr_node));
fold_convert (TREE_TYPE (base), nullptr_node));
/* This is a compiler generated comparison, don't emit /* This is a compiler generated comparison, don't emit
e.g. -Wnonnull-compare warning for it. */ e.g. -Wnonnull-compare warning for it. */
if (TREE_CODE (cond) == NE_EXPR) TREE_NO_WARNING (cond) = 1;
TREE_NO_WARNING (cond) = 1; body = build3_loc (input_location, COND_EXPR, void_type_node,
body = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, body, integer_zero_node);
cond, body, integer_zero_node);
body = build1 (NOP_EXPR, void_type_node, body); body = build1 (NOP_EXPR, void_type_node, body);
if (controller) if (controller)
...@@ -4523,9 +4521,8 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete, ...@@ -4523,9 +4521,8 @@ build_delete (tree otype, tree addr, special_function_kind auto_delete,
{ {
/* Handle deleting a null pointer. */ /* Handle deleting a null pointer. */
warning_sentinel s (warn_address); warning_sentinel s (warn_address);
ifexp = fold (cp_build_binary_op (input_location, ifexp = cp_build_binary_op (input_location, NE_EXPR, addr,
NE_EXPR, addr, nullptr_node, nullptr_node, complain);
complain));
if (ifexp == error_mark_node) if (ifexp == error_mark_node)
return error_mark_node; return error_mark_node;
/* This is a compiler generated comparison, don't emit /* This is a compiler generated comparison, don't emit
......
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> 2016-02-24 Marek Polacek <polacek@redhat.com>
PR c/69819 PR c/69819
......
// 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" }
}
// 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" }
}
// 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" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment