On Wed, Feb 24, 2021 at 01:32:02PM +0100, Richard Biener wrote: > Small comment about the patch below, which otherwise is OK: > > I think that !INTEGRAL_TYPE_P (TREE_TYPE (innerop)) is a sufficient > condition here.
Unfortunately as shown during the bootstrap, that patch contained a fatal thinko, > > + default: > > + break; for default: we need return; Here is a version of the patch that passed bootstrap/regtest on x86_64-linux and i686-linux, ok for trunk? 2021-02-24 Jakub Jelinek <ja...@redhat.com> PR tree-optimization/80635 * tree-vrp.c (vrp_simplify_cond_using_ranges): Also handle VIEW_CONVERT_EXPR if modes are the same, innerop is integral and has mode precision. * g++.dg/warn/pr80635-1.C: New test. * g++.dg/warn/pr80635-2.C: New test. --- gcc/tree-vrp.c.jj 2021-02-24 12:56:58.573939572 +0100 +++ gcc/tree-vrp.c 2021-02-24 13:05:22.675326780 +0100 @@ -4390,11 +4390,22 @@ vrp_simplify_cond_using_ranges (vr_value gimple *def_stmt = SSA_NAME_DEF_STMT (op0); tree innerop; - if (!is_gimple_assign (def_stmt) - || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt))) + if (!is_gimple_assign (def_stmt)) return; - innerop = gimple_assign_rhs1 (def_stmt); + switch (gimple_assign_rhs_code (def_stmt)) + { + CASE_CONVERT: + innerop = gimple_assign_rhs1 (def_stmt); + break; + case VIEW_CONVERT_EXPR: + innerop = TREE_OPERAND (gimple_assign_rhs1 (def_stmt), 0); + if (!INTEGRAL_TYPE_P (TREE_TYPE (innerop))) + return; + break; + default: + return; + } if (TREE_CODE (innerop) == SSA_NAME && !POINTER_TYPE_P (TREE_TYPE (innerop)) --- gcc/testsuite/g++.dg/warn/pr80635-1.C.jj 2021-02-24 12:24:15.176834532 +0100 +++ gcc/testsuite/g++.dg/warn/pr80635-1.C 2021-02-24 12:24:15.176834532 +0100 @@ -0,0 +1,46 @@ +// PR tree-optimization/80635 +// { dg-do compile { target c++11 } } +// { dg-options "-O2 -Wmaybe-uninitialized" } + +using size_t = decltype (sizeof (1)); +inline void *operator new (size_t, void *p) { return p; } +template<typename T> +struct optional +{ + optional () : m_dummy (), live (false) {} + void emplace () { new (&m_item) T (); live = true; } + ~optional () { if (live) m_item.~T (); } + + union + { + struct {} m_dummy; + T m_item; + }; + bool live; +}; + +extern int get (); +extern void set (int); + +struct A +{ + A () : m (get ()) {} + ~A () { set (m); } // { dg-bogus "may be used uninitialized in this function" } + + int m; +}; + +struct B +{ + B (); + ~B (); +}; + +void func () +{ + optional<A> maybe_a; + optional<B> maybe_b; + + maybe_a.emplace (); + maybe_b.emplace (); +} --- gcc/testsuite/g++.dg/warn/pr80635-2.C.jj 2021-02-24 12:24:15.176834532 +0100 +++ gcc/testsuite/g++.dg/warn/pr80635-2.C 2021-02-24 12:24:15.176834532 +0100 @@ -0,0 +1,31 @@ +// PR tree-optimization/80635 +// { dg-do compile { target c++17 } } +// { dg-options "-O2 -Wmaybe-uninitialized" } + +#include <optional> + +extern int get (); +extern void set (int); + +struct A +{ + A () : m (get ()) {} + ~A () { set (m); } // { dg-bogus "may be used uninitialized in this function" } + + int m; +}; + +struct B +{ + B (); + ~B (); +}; + +void func () +{ + std::optional<A> maybe_a; + std::optional<B> maybe_b; + + maybe_a.emplace (); + maybe_b.emplace (); +} Jakub