Message ID | 20221027153906.24773-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: -Wdangling-reference and system headers | expand |
On 10/27/22 11:39, Marek Polacek wrote: > I got this testcase: > > auto f() -> std::optional<std::string>; > for (char c : f().value()) { } > > which has a dangling reference: std::optional<T>::value returns > a reference to the contained value, but here it's the f() temporary. > We warn, which is great, but only with -Wsystem-headers, because > the function comes from a system header and warning_enabled_at used > in do_warn_dangling_reference checks diagnostic_report_warnings_p, > which in this case returned false so we didn't warn. > > Fixed as below. I could also override dc_warn_system_headers so that > the warning is enabled in system headers always. With that, I found one > issue in libstdc++: > > libstdc++-v3/include/bits/fs_path.h:1265:15: warning: possibly dangling reference to a temporary [-Wdangling-reference] > 1265 | auto& __last = *--end(); > | ^~~~~~ > > which looks like a true positive as well. > > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > gcc/cp/ChangeLog: > > * call.cc (maybe_warn_dangling_reference): Enable the warning in > system headers if the decl isn't in a system header. > > gcc/testsuite/ChangeLog: > > * g++.dg/warn/Wdangling-reference4.C: New test. > --- > gcc/cp/call.cc | 7 +++++++ > gcc/testsuite/g++.dg/warn/Wdangling-reference4.C | 14 ++++++++++++++ > 2 files changed, 21 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference4.C > > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc > index 951b9fd2a88..c7c7a122045 100644 > --- a/gcc/cp/call.cc > +++ b/gcc/cp/call.cc > @@ -13539,6 +13539,13 @@ maybe_warn_dangling_reference (const_tree decl, tree init) > return; > if (!TYPE_REF_P (TREE_TYPE (decl))) > return; > + /* Don't suppress the diagnostic just because the call comes from > + a system header. If the DECL is not in a system header, or if > + -Wsystem-headers was provided, warn. */ > + auto wsh > + = make_temp_override (global_dc->dc_warn_system_headers, > + (!in_system_header_at (DECL_SOURCE_LOCATION (decl)) > + || global_dc->dc_warn_system_headers)); Hmm, this is OK, but maybe we want a warning_enabled_at_ignore_system_header? > if (tree call = do_warn_dangling_reference (init)) > { > auto_diagnostic_group d; > diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C > new file mode 100644 > index 00000000000..aee7a29019b > --- /dev/null > +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C > @@ -0,0 +1,14 @@ > +// { dg-do compile { target c++17 } } > +// { dg-options "-Wdangling-reference" } > +// Check that we warn here even without -Wsystem-headers. > + > +#include <optional> > +#include <string> > + > +auto f() -> std::optional<std::string>; > + > +void > +g () > +{ > + for (char c : f().value()) { (void) c; } // { dg-warning "dangling reference" } > +} > > base-commit: f95d3d5de72a1c43e8d529bad3ef59afc3214705
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 951b9fd2a88..c7c7a122045 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -13539,6 +13539,13 @@ maybe_warn_dangling_reference (const_tree decl, tree init) return; if (!TYPE_REF_P (TREE_TYPE (decl))) return; + /* Don't suppress the diagnostic just because the call comes from + a system header. If the DECL is not in a system header, or if + -Wsystem-headers was provided, warn. */ + auto wsh + = make_temp_override (global_dc->dc_warn_system_headers, + (!in_system_header_at (DECL_SOURCE_LOCATION (decl)) + || global_dc->dc_warn_system_headers)); if (tree call = do_warn_dangling_reference (init)) { auto_diagnostic_group d; diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C new file mode 100644 index 00000000000..aee7a29019b --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference4.C @@ -0,0 +1,14 @@ +// { dg-do compile { target c++17 } } +// { dg-options "-Wdangling-reference" } +// Check that we warn here even without -Wsystem-headers. + +#include <optional> +#include <string> + +auto f() -> std::optional<std::string>; + +void +g () +{ + for (char c : f().value()) { (void) c; } // { dg-warning "dangling reference" } +}