Bug 105646 - g++ does not raise "xxx may be used uninitialized" warning on dead code when optimizing
Summary: g++ does not raise "xxx may be used uninitialized" warning on dead code when ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 12.1.0
: P3 normal
Target Milestone: 13.0
Assignee: Richard Biener
URL: https://gcc.gnu.org/pipermail/gcc-pat...
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2022-05-18 14:07 UTC by cfy1990
Modified: 2022-10-27 00:54 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 13.0
Known to fail:
Last reconfirmed: 2022-08-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description cfy1990 2022-05-18 14:07:22 UTC
g++ version: g++ (Compiler-Explorer-Build-gcc--binutils-2.38) 12.1.0
Code link: https://godbolt.org/z/5MansKa5c
Compile arguments: -std=c++11  -Wextra -Wall -O2

Code:

int f1();
int f2(){
    bool v2{v2}; // used uninitialized warning
    auto const & a = f1();
    return a;
}
int f3(){
    auto const & a = f1();
    bool v3{v3}; // no warning in g++, got uninitialized warning in clang
    return a;
}
Comment 1 cfy1990 2022-05-18 14:13:29 UTC
When compile without -O2, g++ will generate "'v3' may be used uninitialized" warning.
code link: https://godbolt.org/z/r3sY4srx9
Comment 2 Richard Biener 2022-08-19 13:11:39 UTC
The issue is that for f3() we'd emit a may-uninitialized warning because f1()
could have thrown and thus v3{v3} is only executed conditionally.  For f2()
v2{v2} is always executed (when f2 is entered).  The late diagnostic pass
that would emit may-uninitialized warnings doesn't get to see the v3{v3}
initialization because it was removed as dead code.

When not optimizing we choose to diagnose may-uninit before eliminating v3{v3}.

Confirmed.  Not sure if we want to fix this.  We eventually might use a
different predicate than post-domination for whether a stmt is considered
always executed (ignoring EH and abnormal control flow).  Greedily
following "fallthru" edges might work for this, also implementing the
unreachable edge honoring the ??? comment says.

I have a patch.
Comment 3 GCC Commits 2022-09-29 08:24:02 UTC
The master branch has been updated by Richard Biener <rguenth@gcc.gnu.org>:

https://gcc.gnu.org/g:a1cd4d52d6ef90b977fb2d80c1cf17f3efa5b01d

commit r13-2926-ga1cd4d52d6ef90b977fb2d80c1cf17f3efa5b01d
Author: Richard Biener <rguenther@suse.de>
Date:   Fri Aug 19 15:11:14 2022 +0200

    tree-optimization/105646 - re-interpret always executed in uninit diag
    
    The following fixes PR105646, not diagnosing
    
    int f1();
    int f3(){
        auto const & a = f1();
        bool v3{v3};
        return a;
    }
    
    with optimization because the early uninit diagnostic pass only
    diagnoses always executed cases.  The patch does this by
    re-interpreting what always executed means and choosing to
    ignore exceptional and abnormal control flow for this.  At the
    same time it improves things as suggested in a comment - when
    the value-numbering run done without optimizing figures there's
    a fallthru path, consider blocks on it as always executed.
    
            PR tree-optimization/105646
            * tree-ssa-uninit.cc (warn_uninitialized_vars): Pre-compute
            the set of fallthru reachable blocks from function entry
            and use that to determine wlims.always_executed.
    
            * g++.dg/uninit-pr105646.C: New testcase.
Comment 4 Richard Biener 2022-09-29 08:24:31 UTC
Fixed on trunk.