Bug 108667 - Spurious "may be used uninitialized [-Wmaybe-uninitialized]" warning
Summary: Spurious "may be used uninitialized [-Wmaybe-uninitialized]" warning
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 12.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks: Wuninitialized
  Show dependency treegraph
 
Reported: 2023-02-03 22:02 UTC by Alvaro Begue
Modified: 2023-02-06 15:19 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alvaro Begue 2023-02-03 22:02:29 UTC
I am using g++-12.1.0 on x86-64, but g++-12.2.0 in godbolt.org shows the same problem

The options are -O3 -Wmaybe-uninitialized .

The code:

#include <functional>

struct S {
    S(std::function<void()> f) : f(f) {}

    std::function<void()> g;
    std::function<void()> f;
};

int main() {
    S s([](){});
    s.f();
}

Compiler output (from godbolt.org):
In file included from /opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/functional:59,
                 from <source>:1:
In copy constructor 'std::function<_Res(_ArgTypes ...)>::function(const std::function<_Res(_ArgTypes ...)>&) [with _Res = void; _ArgTypes = {}]',
    inlined from 'S::S(std::function<void()>)' at <source>:4:34,
    inlined from 'int main()' at <source>:11:15:
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/std_function.h:391:17: warning: '<anonymous>' may be used uninitialized [-Wmaybe-uninitialized]
  391 |             __x._M_manager(_M_functor, __x._M_functor, __clone_functor);
      |             ~~~~^~~~~~~~~~
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/std_function.h: In function 'int main()':
/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/std_function.h:267:7: note: by argument 2 of type 'const std::_Any_data&' to 'static bool std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_manager(std::_Any_data&, const std::_Any_data&, std::_Manager_operation) [with _Res = void; _Functor = main()::<lambda()>; _ArgTypes = {}]' declared here
  267 |       _M_manager(_Any_data& __dest, const _Any_data& __source,
      |       ^~~~~~~~~~
<source>:11:15: note: '<anonymous>' declared here
   11 |     S s([](){});
      |               ^
Compiler returned: 0
Comment 1 Andrew Pinski 2023-02-04 00:07:10 UTC
This is partly caused by not inlining everything as main is marked as called once.
If instead I call main, main1, the warning goes away and the following call is inlined now:
  std::_Function_handler<void(), main()::<lambda()> >::_M_manager (&MEM[(struct function *)&s + 32B].D.47025._M_functor, &D.47426.D.47025._M_functor, 2);

The warning in this case is about D.47426 which does not have any initialization before the call here.
Note the call with last operand as 2 does not actually do anything and just returns.

I don't know the best way to solve this specific case as it depends on inlining heurstics.

Question for the reporter, was this a reduction from some real code or did you just notice the warning while testing some code?
Comment 2 Alvaro Begue 2023-02-04 00:33:30 UTC
Yes, this is a reduction of real code. I'm writing a signal class and I wrote a small test for it. It worked fine when compiling unoptimized, but the optimized version gave me this odd warning.

Would it be interesting to see the original code? It's only around 50 lines of code.
Comment 3 Richard Biener 2023-02-06 07:47:53 UTC
Yes, having the original code as well would be nice.
Comment 4 Alvaro Begue 2023-02-06 15:19:56 UTC
Original code:

#include <functional>
#include <vector>
#include <iostream>

template <typename ReturnType, typename... ArgumentTypes>
class Signal {
public:
  using Slot = std::function<ReturnType(ArgumentTypes...)>;
  using FoldingFunction = std::function<ReturnType(ReturnType, ReturnType)>;
  
  Signal(FoldingFunction fold, ReturnType initial)
    : fold(fold), initial(initial) {}
  
  void connect(Slot slot) {
    slots.push_back(slot);
  }
  
  ReturnType operator() (ArgumentTypes... arguments) {
    ReturnType result = initial;
    
    for (const auto &slot : slots)
      result = fold(result, slot(arguments...));
    
    return result;
  }
  
private:
  std::vector<Slot> slots;
  FoldingFunction fold;
  ReturnType initial;
};


int four() { return 4; }

int five() { return 5; }

int main() {
  Signal<int> get_total([](int cumulative_value, int new_term){
    return cumulative_value + new_term;
  }, 0);
  get_total.connect(four);
  get_total.connect(five);
  std::cout << get_total() << '\n';
}