Bug 2183353 - Unable to suppress -Wmaybe-uninitialized from system header with -01 and above
Summary: Unable to suppress -Wmaybe-uninitialized from system header with -01 and above
Keywords:
Status: CLOSED UPSTREAM
Alias: None
Product: Red Hat Developer Toolset
Classification: Red Hat
Component: gcc
Version: DTS 12.1 RHEL 7
Hardware: x86_64
OS: Linux
unspecified
high
Target Milestone: alpha
: 9.1
Assignee: Marek Polacek
QA Contact: Martin Cermak
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2023-03-30 22:41 UTC by Jonathan Sweemer
Modified: 2023-07-18 14:10 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2023-04-19 20:32:40 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
Standalone repro for the issue being reported (3.21 KB, text/plain)
2023-03-30 22:41 UTC, Jonathan Sweemer
no flags Details


Links
System ID Private Priority Status Summary Last Updated
GNU Compiler Collection 109559 0 P3 UNCONFIRMED [12/13/14 Regression] Unexpected -Wmaybe-uninitialized warning when inlining with system header 2023-04-19 20:32:39 UTC
Red Hat Issue Tracker DTS-569 0 None None None 2023-03-30 22:42:20 UTC

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.


Note You need to log in before you can comment on or make changes to this bug.