[Bug c++/65201] New: range-for range-init containing variable named like for-range-declaration iterates over uninitialized for-range-declaration
bloerwald at googlemail dot com
gcc-bugzilla@gcc.gnu.org
Wed Feb 25 10:33:00 GMT 2015
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)
More information about the Gcc-bugs
mailing list