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

            Bug ID: 65201
           Summary: range-for range-init containing variable named like
                    for-range-declaration iterates over uninitialized
                    for-range-declaration
           Product: gcc
           Version: 4.9.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bloerwald at googlemail dot com

#include <iostream>
    #include <string>
    #include <vector>

    template<typename T>
      std::vector<T> split (T in, typename T::value_type delim);
    // … see below

    void choke (std::string foo)
    {
      for (std::string foo : split (foo, ' '))
      {
        std::cout << foo << std::endl;
      }
    }

    int main (int, char**)
    {
      choke ("foo bar baz");
      return 0;
    }

The above compiles and runs fine with clang 3.5.1:

    $ clang++ -Weverything --std=c++11 gcc_range_for_choke.cpp -o
gcc_range_for_choke
    gcc_range_for_choke.cpp:33:20: warning: declaration shadows a local
variable [-Wshadow]
      for (std::string foo : split (foo, ' '))
    [… other warnings]
    $ ./gcc_range_for_choke
    foo
    bar
    baz

but fails miserably with gcc 4.9.2,

    $ c++ --std=c++11 -Wall -Wextra gcc_range_for_choke.cpp -o
gcc_range_for_choke -fno-strict-aliasing -fwrapv
-fno-aggressive-loop-optimizations
    gcc_range_for_choke.cpp:31:25: warning: unused parameter ‘foo’
[-Wunused-parameter]
     void choke (std::string foo)
                             ^
    $ ./gcc_range_for_choke
    Segmentation fault

(The segfault comes from directly accessing the unitialized `T in`.)

I realize what happens, but according to what I understand in the standard, it
has to be equivalent to

    {
      auto && __range = range-init;
      for ( auto __begin = begin-expr, __end = end-expr; __begin != __end;
++__begin )
      {
        for-range-declaration = *__begin;
        statement
      }
    }

The (clang reported) shadowing is real, but `range-init` most certainly can't
refer to `for-range-declaration`, as of what I understand.


Bonus: Badly implemented split for completeness:

    template<typename T>
      std::vector<T> split (T in, typename T::value_type delim)
    {
      std::vector<T> ret;
      T key;
      for (auto const& e : in)
      {
        if (e == delim)
        {
          ret.push_back (key);
          key.clear();
        }
        else
        {
          key.push_back (e);
        }
      }
      if (!key.empty())
      {
        ret.push_back (key);
      }
      return ret;
    }

Note: confirmed to exist on 4.8.2, untested on 4.9.3, 5.0.

    $ gcc -v
    Using built-in specs.
    COLLECT_GCC=gcc
   
COLLECT_LTO_WRAPPER=/p/hpc/soft/gcc/4.9.2/libexec/gcc/x86_64-unknown-linux-gnu/4.9.2/lto-wrapper
    Target: x86_64-unknown-linux-gnu
    Configured with: ./configure --prefix=/p/hpc/soft/gcc/4.9.2
    Thread model: posix
    gcc version 4.9.2 (GCC)

Reply via email to