Bug 94695 - Implement -Wrange-loop-analysis
Summary: Implement -Wrange-loop-analysis
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P3 enhancement
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: diagnostic
: 80542 (view as bug list)
Depends on:
Blocks: new-warning, new_warning
  Show dependency treegraph
 
Reported: 2020-04-21 14:37 UTC by Marek Polacek
Modified: 2021-05-10 10:03 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-09-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Polacek 2020-04-21 14:37:43 UTC
This options contains a sub-option -Wrange-loop-construct which warns about:

#include <string>
#include <vector>

int main()
{
    std::vector<std::string> lol;
    for (const auto it : lol) { }
}

<source>:7:21: warning: loop variable 'it' creates a copy from type 'const std::__cxx11::basic_string<char>' [-Wrange-loop-construct]

    for (const auto it : lol) { }

                    ^

<source>:7:10: note: use reference type 'const std::__cxx11::basic_string<char> &' to prevent copying

    for (const auto it : lol) { }

         ^~~~~~~~~~~~~~~

                    &

1 warning generated.

We should consider adding something like that, too, in GCC 11.
Comment 1 GCC Commits 2020-09-29 23:03:54 UTC
The master branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:969baf03acd8124345617cea125b148568c7370a

commit r11-3539-g969baf03acd8124345617cea125b148568c7370a
Author: Marek Polacek <polacek@redhat.com>
Date:   Thu Sep 24 14:30:50 2020 -0400

    c++: Implement -Wrange-loop-construct [PR94695]
    
    This new warning can be used to prevent expensive copies inside range-based
    for-loops, for instance:
    
      struct S { char arr[128]; };
      void fn () {
        S arr[5];
        for (const auto x : arr) {  }
      }
    
    where auto deduces to S and then we copy the big S in every iteration.
    Using "const auto &x" would not incur such a copy.  With this patch the
    compiler will warn:
    
    q.C:4:19: warning: loop variable 'x' creates a copy from type 'const S' [-Wrange-loop-construct]
        4 |   for (const auto x : arr) {  }
          |                   ^
    q.C:4:19: note: use reference type 'const S&' to prevent copying
        4 |   for (const auto x : arr) {  }
          |                   ^
          |                   &
    
    As per Clang, this warning is suppressed for trivially copyable types
    whose size does not exceed 64B.  The tricky part of the patch was how
    to figure out if using a reference would have prevented a copy.  To
    that point, I'm using the new function called ref_conv_binds_directly_p.
    
    This warning is enabled by -Wall.  Further warnings of similar nature
    should follow soon.
    
    gcc/c-family/ChangeLog:
    
            PR c++/94695
            * c.opt (Wrange-loop-construct): New option.
    
    gcc/cp/ChangeLog:
    
            PR c++/94695
            * call.c (ref_conv_binds_directly_p): New function.
            * cp-tree.h (ref_conv_binds_directly_p): Declare.
            * parser.c (warn_for_range_copy): New function.
            (cp_convert_range_for): Call it.
    
    gcc/ChangeLog:
    
            PR c++/94695
            * doc/invoke.texi: Document -Wrange-loop-construct.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/94695
            * g++.dg/warn/Wrange-loop-construct.C: New test.
Comment 2 Marek Polacek 2020-09-29 23:05:29 UTC
First part of the warning is now implemented.
Comment 3 GCC Commits 2020-11-21 21:28:51 UTC
The master branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

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

commit r11-5234-gc51e31a06f2c740c55852a683aa7ffdc20417362
Author: Marek Polacek <polacek@redhat.com>
Date:   Mon Nov 9 21:15:33 2020 -0500

    c++: Extend -Wrange-loop-construct for binding-to-temp [PR94695]
    
    This patch finishes the second half of -Wrange-loop-construct I promised
    to implement: it warns when a loop variable in a range-based for-loop is
    initialized with a value of a different type resulting in a copy.  For
    instance:
    
      int arr[10];
      for (const double &x : arr) { ... }
    
    where in every iteration we have to create and destroy a temporary value
    of type double, to which we bind the reference.  This could negatively
    impact performance.
    
    As per Clang, this doesn't warn when the range returns a copy, hence the
    glvalue_p check.
    
    gcc/ChangeLog:
    
            PR c++/94695
            * doc/invoke.texi: Update the -Wrange-loop-construct description.
    
    gcc/cp/ChangeLog:
    
            PR c++/94695
            * parser.c (warn_for_range_copy): Warn when the loop variable is
            initialized with a value of a different type resulting in a copy.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/94695
            * g++.dg/warn/Wrange-loop-construct2.C: New test.
Comment 4 Marek Polacek 2020-11-21 21:30:40 UTC
Implemented in GCC 11.
Comment 5 Jonathan Wakely 2021-05-10 10:03:36 UTC
*** Bug 80542 has been marked as a duplicate of this bug. ***