Bug 2183353

Summary: Unable to suppress -Wmaybe-uninitialized from system header with -01 and above
Product: Red Hat Developer Toolset Reporter: Jonathan Sweemer <sweemer>
Component: gccAssignee: Marek Polacek <mpolacek>
gcc sub component: gcc-toolset-12 QA Contact: Martin Cermak <mcermak>
Status: CLOSED UPSTREAM Docs Contact:
Severity: high    
Priority: unspecified CC: mpolacek
Version: DTS 12.1 RHEL 7   
Target Milestone: alpha   
Target Release: 9.1   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2023-04-19 20:32:40 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Standalone repro for the issue being reported none

Description Jonathan Sweemer 2023-03-30 22:41:07 UTC
Created attachment 1954800 [details]
Standalone repro for the issue being reported

Description of problem:

-Wmaybe-uninitialized is not being suppressed for a system header at optimization level -O1 and above.

The attached code comes from the QuantLib project and I have modified it to demonstrate the issue as a self-contained repro.

Version-Release number of selected component (if applicable):

1. gcc-toolset-12-gcc.x86_64 12.1.1-3.4.el8_7 @rhel-8-for-x86_64-appstream-rpms
2. boost-devel.x86_64 1.66.0-13.el8 @rhel-8-for-x86_64-appstream-rpms

Steps to Reproduce:

1. First, compile the attached file with -Wmaybe-uninitialized and -O0 to confirm no warnings:

$ g++ -Wmaybe-uninitialized -O0 -c main.cpp

2. Next, compile the attached file with -Wmaybe-uninitialized -O1 and confirm that the following warning is emitted:

$ g++ -Wmaybe-uninitialized -O1 -c main.cpp
In file included from /usr/include/boost/function/detail/maybe_include.hpp:22,
                 from /usr/include/boost/function/detail/function_iterate.hpp:14,
                 from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:52,
                 from /usr/include/boost/function.hpp:70,
                 from main.cpp:1:
In member function ‘void boost::function1<R, T1>::move_assign(boost::function1<R, T1>&) [with R = double; T0 = double]’,
    inlined from ‘void boost::function1<R, T1>::swap(boost::function1<R, T1>&) [with R = double; T0 = double]’ at /usr/include/boost/function/function_template.hpp:858:22,
    inlined from ‘typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0)>&>::type boost::function<R(T0)>::operator=(Functor) [with Functor = FilonIntegral::integrate(const boost::function<double(double)>&, double, double) const::<lambda(double)>; R = double; T0 = double]’ at /usr/include/boost/function/function_template.hpp:1114:22,
    inlined from ‘virtual double FilonIntegral::integrate(const boost::function<double(double)>&, double, double) const’ at main.cpp:110:59:
/usr/include/boost/function/function_template.hpp:986:13: warning: ‘<unnamed>.boost::function<double(double)>::<unnamed>.boost::function1<double, double>::<anonymous>.boost::function_base::functor’ may be used uninitialized [-Wmaybe-uninitialized]
  986 |             this->functor = f.functor;
      |             ^~~~
/usr/include/boost/function/function_template.hpp: In member function ‘virtual double FilonIntegral::integrate(const boost::function<double(double)>&, double, double) const’:
/usr/include/boost/function/function_template.hpp:1114:5: note: ‘<anonymous>’ declared here
 1114 |     self_type(f).swap(*this);
      |     ^~~~~~~~~~~~

Actual results:

As shown above

Expected results:

I expect no warning to be emitted for boost headers installed in /usr/include, because as far as I understand, /usr/include is a system header directory by default; i.e. implicitly passed as `-isystem /usr/include` to the compiler.

Additional info:

I am running Red Hat Enterprise Linux release 8.7 (Ootpa)

Comment 1 Marek Polacek 2023-04-05 21:57:33 UTC
Hi, thanks for the test.

That a middle-end warning such as -Wmaybe-uninitialized triggers with optimizations turned on
but not when optimizations are turned off is normal.  You can visit
<https://developers.redhat.com/blog/2019/03/13/understanding-gcc-warnings-part-2#limitations_of_middle_end_warnings>
for more information on that subject.

I could reproduce the problem with boost-devel-1.66 but not boost-devel-1.78.  Turns out that
boost has disabled the warning; git log function_template.hpp shows

commit b75386f628b46f1060a20b6e015931bac37b7da7 (origin/feature/drone)
Author: Peter Dimov <pdimov>
Date:   Sun Feb 12 04:50:04 2023 +0200

    Avoid -Wuninitialized under GCC 11.3

commit 9229ed30103df59a4f989ca0235b0d1026bf6e1c
Author: Peter Dimov <pdimov>
Date:   Sun Feb 12 04:47:38 2023 +0200

    Avoid another -Wmaybe-uninitialized under GCC 11/12

commit 16fca8368b5da14c4bcad977c2738dc6e482e1b7 (tag: boost-1.81.0.beta1, tag: boost-1.81.0, tag: boost-1.80.0.beta1, tag: boost-1.80.0, origin/feature/issue-42)
Author: Peter Dimov <pdimov>
Date:   Mon May 30 20:25:13 2022 +0300

    Keep -Wmaybe-uninitialized disabled

commit 4cf7c718b873223cbab6f8188bea2034f27ba99d
Merge: 389f886 5b4e279
Author: Peter Dimov <pdimov>
Date:   Mon May 30 19:56:08 2022 +0300

    Merge branch 'gcc12-Wuninitialized' of https://github.com/jngrad/boost-function into feature/issue-42

commit abc1bf9b4ae3f45251d17b451c69c3e79dfd0cf6 (origin/feature/update-ci)
Author: Peter Dimov <pdimov>
Date:   Mon May 30 18:44:07 2022 +0300

    Extend GCC 11 workaround to GCC 12 as well

commit 5b4e2797a28f9477d2df5fa915409dac73ff00c6
Author: Jean-Noël Grad <jgrad.de>
Date:   Mon May 30 16:16:41 2022 +0200

    Avoid -Wuninitialized warnings in GCC 12

commit 277757befc321bda3b9d8038ee59ae6e4616cdca
Author: Peter Dimov <pdimov>
Date:   Thu Dec 16 06:18:06 2021 +0200

    Disable -Wmaybe-uninitialized in function_template.hpp for GCC 11

commit 7c90434317894f1a0c63c7a395ddf569eff1d308
Author: Romain Geissler <romain.geissler>
Date:   Fri Mar 27 18:56:14 2020 +0000

    Avoid -Wmaybe-uninitialized warnings in gcc (issue #27).

so with newer boost you wouldn't see the warning.  If you can't update boost, you
can do

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#include <boost/function.hpp>
#pragma GCC diagnostic pop

in your project to suppress the warning.

Just for the record, GCC started warning with

commit 6feb628a706e86eb3f303aff388c74bdb29e7381
Author: Martin Sebor <msebor>
Date:   Fri Jul 2 16:16:31 2021 -0600

    Improve warning suppression for inlined functions [PR98512].

Comment 2 Jonathan Sweemer 2023-04-07 04:41:56 UTC
Hi Marek, thanks very much for looking into this and for the explanations.

I understand that the optimization level affects which compiler warnings are generated, but my question is why aren't those warnings suppressed for system headers?

According to the GCC documentation[1], "All warnings, other than those generated by ‘#warning’ (see Diagnostics), are suppressed while GCC is processing a system header." Is this not true for gcc-toolset-12? 

I read the article that you linked and it doesn't specifically say that the compiler will not suppress warnings for system headers, so I still don't expect to see any warnings from the boost headers installed in /usr/include, which is a system header directory. Can you help clarify why the warnings are not being suppressed?

[1] https://gcc.gnu.org/onlinedocs/cpp/System-Headers.html

Comment 3 Marek Polacek 2023-04-18 22:02:26 UTC
Sorry for the slow response.  I think you're right on the money, and there's something strange going on.

It all seems to be due to
106         f1 = [](double x) -> double { return std::sin(x); };
being inlined, the problem doesn't reproduce with -fno-inline.

We have an inlining context containing locations for each call site along
the inlining stack: struct inlining_info.  It has a stack of locations,
and a flag that says whether all of them come from a system header.  If so,
we don't warn:

1548   if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1549     /* Bail if the warning is not to be reported because all locations
1550        in the inlining stack (if there is one) are in system headers.  */
1551     return false;

but in this test diagnostic->m_iinfo.m_allsyslocs is false because the inlining
causes that the outermost context is the bz.C file, which is not a system header.

Reduced to:

# 0 "" 3
struct function_base {
  has_trivial_copy_and_destroy() const;
  int functor;
};
struct function1 : function_base {
  swap(function1) { has_trivial_copy_and_destroy(); }
};
struct function : function1 {
  template <typename Functor> operator=(Functor) { swap(*this); }
};
# 4 ""
struct FilonIntegral {
  double integrate() const;
};
double FilonIntegral::integrate() const {
  function f1;
  f1 = [] {};
  return 0;
}

This needs to be fixed upstream first (if it is indeed a bug).  It is not special to the GCC Toolset.

Comment 4 Jonathan Sweemer 2023-04-19 02:51:13 UTC
When you say upstream, do you mean in the main GCC repository?

If so, should I file a bug report with GCC, or is it something that RedHat could help coordinate?

Comment 5 Marek Polacek 2023-04-19 20:32:40 UTC
> When you say upstream, do you mean in the main GCC repository?

Correct.

I've opened <https://gcc.gnu.org/PR109559>.  Let's see what other developers think about it.  And let's move the discussion to the upstream PR.