[Bug c++/106393] Add warnings for common dangling problems

cvs-commit at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Oct 26 19:14:11 GMT 2022


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106393

--- Comment #1 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

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

commit r13-3511-gd2249cd9adf5ae638577139177a50f7e62d8abd9
Author: Marek Polacek <polacek@redhat.com>
Date:   Fri Oct 14 10:05:57 2022 -0400

    c++: Implement -Wdangling-reference [PR106393]

    This patch implements a new experimental warning (enabled by -Wall) to
    detect references bound to temporaries whose lifetime has ended.  The
    primary motivation is the Note in
    <https://en.cppreference.com/w/cpp/algorithm/max>:

      Capturing the result of std::max by reference produces a dangling
reference
      if one of the parameters is a temporary and that parameter is returned:

      int n = 1;
      const int& r = std::max(n-1, n+1); // r is dangling

    That's because both temporaries for n-1 and n+1 are destroyed at the end
    of the full expression.  With this warning enabled, you'll get:

    g.C:3:12: warning: possibly dangling reference to a temporary
[-Wdangling-reference]
        3 | const int& r = std::max(n-1, n+1);
          |            ^
    g.C:3:24: note: the temporary was destroyed at the end of the full
expression 'std::max<int>((n - 1), (n + 1))'
        3 | const int& r = std::max(n-1, n+1);
          |                ~~~~~~~~^~~~~~~~~~

    The warning works by checking if a reference is initialized with a function
    that returns a reference, and at least one parameter of the function is
    a reference that is bound to a temporary.  It assumes that such a function
    actually returns one of its arguments!  (I added code to check_return_expr
    to suppress the warning when we've seen the definition of the function
    and we can say that it can return a variable with static storage
    duration.)

    It warns when the function in question is a member function, but only if
    the function is invoked on a temporary object, otherwise the warning
    would emit loads of warnings for valid code like obj.emplace<T>({0}, 0).
    It does detect the dangling reference in:

      struct S {
        const S& self () { return *this; }
      };
      const S& s = S().self();

    It warns in member initializer lists as well:

      const int& f(const int& i) { return i; }
      struct S {
        const int &r;
        S() : r(f(10)) { }
      };

    I've run the testsuite/bootstrap with the warning enabled by default.
    There were just a few FAILs, all of which look like genuine bugs.
    A bootstrap with the warning enabled by default passed as well.

    When testing a previous version of the patch, there were many FAILs in
    libstdc++'s 22_locale/; all of them because the warning triggered on

      const test_type& obj = std::use_facet<test_type>(std::locale());

    but this code looks valid -- std::use_facet doesn't return a reference
    to its parameter.  Therefore I added a #pragma and code to suppress the
    warning.

            PR c++/106393

    gcc/c-family/ChangeLog:

            * c.opt (Wdangling-reference): New.

    gcc/cp/ChangeLog:

            * call.cc (expr_represents_temporary_p): New, factored out of...
            (conv_binds_ref_to_temporary): ...here.  Don't return false just
            because a ck_base is missing.  Use expr_represents_temporary_p.
            (do_warn_dangling_reference): New.
            (maybe_warn_dangling_reference): New.
            (extend_ref_init_temps): Call maybe_warn_dangling_reference.
            * cp-tree.h: Adjust comment.
            * typeck.cc (check_return_expr): Suppress -Wdangling-reference
            warnings.

    gcc/ChangeLog:

            * doc/invoke.texi: Document -Wdangling-reference.

    libstdc++-v3/ChangeLog:

            * include/bits/locale_classes.tcc: Add #pragma to disable
            -Wdangling-reference with std::use_facet.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp23/elision4.C: Use -Wdangling-reference, add
dg-warning.
            * g++.dg/cpp23/elision7.C: Likewise.
            * g++.dg/warn/Wdangling-pointer-2.C: Use -Wno-dangling-reference.
            * g++.dg/warn/Wdangling-reference1.C: New test.
            * g++.dg/warn/Wdangling-reference2.C: New test.
            * g++.dg/warn/Wdangling-reference3.C: New test.


More information about the Gcc-bugs mailing list