From 2cde02ad062bfb4c2fc230828755c4d669cf37aa Mon Sep 17 00:00:00 2001 From: jakub Date: Wed, 24 Feb 2016 22:01:24 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233684 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 14 ++++++++++++++ gcc/cp/class.c | 7 +++++-- gcc/cp/cp-gimplify.c | 20 ++++++++++++++++++-- gcc/cp/cp-ubsan.c | 13 +++++++++---- gcc/cp/init.c | 17 +++++++---------- gcc/testsuite/ChangeLog | 7 +++++++ gcc/testsuite/g++.dg/ubsan/pr69922.C | 18 ++++++++++++++++++ gcc/testsuite/g++.dg/warn/Wnonnull-compare-6.C | 13 +++++++++++++ gcc/testsuite/g++.dg/warn/Wnonnull-compare-7.C | 19 +++++++++++++++++++ 9 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ubsan/pr69922.C create mode 100644 gcc/testsuite/g++.dg/warn/Wnonnull-compare-6.C create mode 100644 gcc/testsuite/g++.dg/warn/Wnonnull-compare-7.C 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 + + 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 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..43f854c 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 + + 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 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(reinterpret_cast(this)); // { dg-bogus "nonnull argument" } +} + +T * +T::baz () +{ + return static_cast(reinterpret_cast(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 (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" } +} -- 2.7.4