STL push_back optimize cause array subscript is above array bounds - c++

Test environment:
CentOS 7.0 g++ 4.8.2
Arch Linux g++ 4.9.0 20140604 (prerelease)
Arch Linux g++ 4.9.1
Compile command cases:
PASS: g++ -Wall t.cpp
FAIL: g++ -Wall -O2 t.cpp
PASS: g++ -Wall -O2 t.cpp # and replace 2 with 3 on line 13
PASS: g++ -Wall -O2 t.cpp # and comment out line 14
PASS: g++ -Wall -O2 --std=c++11 t.cpp # for g++ 4.8/4.9
The FAIL message:
t.cpp: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(std::vecto
<_Tp, _Alloc>::iterator, const _Tp&) [with _Tp = Object; _Alloc = std::allocator<Ob
ject>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<Object*, s
td::vector<Object> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = Object*]’
t.cpp:17:15: warning: array subscript is above array bounds [-Warray-bounds]
~Object() {};
^
t.cpp:17:15: warning: array subscript is above array bounds [-Warray-bounds]
t.cpp
#include <vector>
class TestCls {
public:
TestCls() {};
virtual ~TestCls() {};
};
class TestCls1 : public TestCls
{
};
class Object {
public:
TestCls m_member[2];
TestCls1 m_member1[2]; // LINE 13, if change to [3] it works.
TestCls1 m_member2[2]; // LINE 14, if comment out this line, it works.
Object() {};
~Object() {}; // LINE 17 the warning line
};
class Container {
public:
std::vector<Object> m_obj;
Container() {};
~Container() {};
};
int main() {
Container con;
Object obj;
con.m_obj.push_back(obj);
}

This is a type of bogus warning generated by GCC due to issues with Value Range Propagation (which is the middle-end pass that generates array bounds warnings) interacting with the various loop optimizer passes (such as loop peeling and loop unrolling). As is mentioned in the various bugzillas linked, these represent missed optimization opportunities as well, but the underlying issue (or issues) in VRP have proved elusive for the GCC developers. That said, reporting this occurrence to the GCC Bugzilla is a good idea, especially since you have a MWE at hand.

I found a solution, but I don't know the reason.
// ...
class Object {
public:
// ...
~Object();
};
Object::~Object() {}; // move to outside LINE 19
//...

gcc -Wall enables all compiler's warning messages. This option should
always be used, in order to generate better code.
So, try delete -Wall. Example:
with -Wall http://goo.gl/d4cces
without -Wall http://goo.gl/4vY2Un

Related

Clang Warning on expression side effects

Given the following source code:
#include <memory>
#include <typeinfo>
struct Base {
virtual ~Base();
};
struct Derived : Base { };
int main() {
std::unique_ptr<Base> ptr_foo = std::make_unique<Derived>();
typeid(*ptr_foo).name();
return 0;
}
and compiled it with:
clang++ -std=c++14 -Wall -Wextra -Werror -Wpedantic -g -o test test.cpp
Enviroment setup:
linux x86_64
clang version 5.0.0
It does not compile because of warning (note -Werror):
error: expression with side effects will be evaluated
despite being used as an operand to 'typeid'
[-Werror,-Wpotentially-evaluated-expression]
typeid(*ptr_foo).name();
(Just a note: GCC does not claim that kind of potential problematic)
Question
Is there a way to get the information about the type pointed by a unique_ptr without generating that kind of warning?
Note: I am not talking about disabling -Wpotentially-evaluated-expression or avoiding -Werror.
Looks like following should work without warnings and give correct result for derived class
std::unique_ptr<Foo> ptr_foo = std::make_unique<Bar>();
if(ptr_foo.get()){
auto& r = *ptr_foo.get();
std::cout << typeid(r).name() << '\n';
}

Is it possible to use a class template in its member functions?

My class is size parameterized. In one of its methods I have to create a temporary array, but I don't know how to pass the class's size template to the member function. This is how I tried:
#include <array>
template<unsigned int N>
class MyClass{
std::array<int,N> m_data;
public:
void myFunc(){
std::array<int,N> tempArray;
}
};
int main(){
MyClass<5> obj;
obj.myFunc();
}
Edit:
Build log:
C:\Windows\system32\cmd.exe /C ""C:/Program Files/mingw-w64/x86_64-6.3.0-win32-seh-rt_v5-rev1/mingw64/bin/mingw32-make.exe" -j6 SHELL=cmd.exe -e -f Makefile"
"----------Building project:[ hatizsak_konyv - Debug ]----------"
mingw32-make.exe[1]: Entering directory 'E:/progi/c++/CodeLite/Other/algoritmusok/dinamikus_programozas/hatizsak_konyv'
"C:/Program Files/mingw-w64/x86_64-6.3.0-win32-seh-rt_v5-rev1/mingw64/bin/g++.exe" -c "E:/progi/c++/CodeLite/Other/algoritmusok/dinamikus_programozas/hatizsak_konyv/main.cpp" -g -O0 -Wall -o ./Debug/main.cpp.o -I. -I.
E:/progi/c++/CodeLite/Other/algoritmusok/dinamikus_programozas/hatizsak_konyv/main.cpp: In instantiation of 'void MyClass<N>::myFunc() [with unsigned int N = 5u]':
E:/progi/c++/CodeLite/Other/algoritmusok/dinamikus_programozas/hatizsak_konyv/main.cpp:15:16: required from here
E:/progi/c++/CodeLite/Other/algoritmusok/dinamikus_programozas/hatizsak_konyv/main.cpp:8:27: warning: unused variable 'tempArray' [-Wunused-variable]
std::array<int,N> tempArray;
^~~~~~~~~
"C:/Program Files/mingw-w64/x86_64-6.3.0-win32-seh-rt_v5-rev1/mingw64/bin/g++.exe" -o ./Debug/hatizsak_konyv #"hatizsak_konyv.txt" -L.
mingw32-make.exe[1]: Leaving directory 'E:/progi/c++/CodeLite/Other/algoritmusok/dinamikus_programozas/hatizsak_konyv'
====1 errors, 1 warnings====
Template parameters are visible inside methods of the template class; the code is correct.
There's no error at all, nor in the provided code example, nor in the build log. The message in the build log is just a warning (with the lines before providing context for it), which correctly warns you about the fact that that variable isn't used, as per the -Wall option provided on the command line. Other than that, the code compiles fine, both on ideone and on my machine (where it gives you exact same warning, not error).
[matteo#teolapkubuntu /tmp]$ g++ -Wall -Wextra -std=c++11 stuff.cpp
stuff.cpp: In instantiation of ‘void MyClass<N>::myFunc() [with unsigned int N = 5u]’:
stuff.cpp:15:16: required from here
stuff.cpp:8:27: warning: unused variable ‘tempArray’ [-Wunused-variable]
std::array<int,N> tempArray;
^~~~~~~~~
The "1 error" message at the end of the build log is just CodeLite misinterpreting the compiler output; there is an open bug about it, with conditions similar to yours.

Defining a constructor of a class in C++

I am currently going through Bjarne Stroustrup's "The C++ Programming Language (4th Edition)" and am trying to understand whether is the following a syntax error or was it the way I compiled it.
According to the following code snippet (extracted from the book), my constructor should look like this:
class Vector {
public:
Vector(int s): elem{new double[s]}, sz{s} {} // Construct a Vector
...
private:
double* elem; // Pointer to the elements
int sz; // The number of elements
};
But, I am unable to compile it unless I change the following as per the suggestion of the error message:
Vector(int s): elem(new double[s]), sz(s) {}
Note: I compiled my C++ codes using the following command through the Mac Terminal:
g++ -ansi -pedantic -Wall Test.cpp -o Test.o
Thank you in advance.
Probably, all you need to do is to compile it for C++ 11:
g++ -std=c++11 -ansi -pedantic -Wall Test.cpp -o Test.o
As #molbdnilo pointed out in a comment, remove -ansi from the command, because this is a synonym for std=c89 or std=c++98.
g++ -std=c++11 -pedantic -Wall Test.cpp -o Test.o

C++ Move constructor won't compile

I have an unfortunate problem. My GCC 4.6.3 compiler refuses to compile my move constructor.
Exchanging line 6 in the example with "MemoryBlock(const MemoryBlock & other)" would make it compile, but not using the below move constructor declaration. Seems like the compiler does not know C+11, even though it should using 4.6.3. Right?
#include <cstddef>
class MemoryBlock
{
public:
MemoryBlock(MemoryBlock && other) //<----------- RAD 6.
{
}
private:
size_t _length; // The length of the resource.
int* _data; // The resource.
};
int main() {
}
Compiler output:
prog.cpp:6:28: error: expected ‘,’ or ‘...’ before ‘&&’ token
prog.cpp:6:36: error: invalid constructor; you probably meant ‘MemoryBlock (const MemoryBlock&)’
make: * [slask] Error 1
GCC version:
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 (Kör från labbsal i skolan)
makefile:
%.out: %.cpp
g++ -g -W -Wall -std=c++0x $*.cpp -o $*.out;
Try -std=c++11 instead of -std=c++0x. While your compiler knows the usage, the -std=c++0x "turns off" those new rules.

Clang reject type_info as incomplete although <typeinfo> is included

I'm lost as to why Clang rejects the following code:
#include <typeinfo>
#include <exception>
const char* get_name( const std::exception_ptr eptr )
{
return eptr.__cxa_exception_type()->name();
}
int main() {}
It OK with GCC, but Clang complains about type_info being an incomplete type:
$ g++-4.7 -std=c++0x -O3 -Wall -Wextra t.cc -o t
$ clang++-3.2 -std=c++0x -O3 -Wall -Wextra t.cc -o t
t.cc:6:37: error: member access into incomplete type 'const class type_info'
return eptr.__cxa_exception_type()->name();
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.7/../../../../include/c++/4.7/bits/exception_ptr.h:144:19: note: forward declaration of
'std::__exception_ptr::type_info'
const class type_info*
^
1 error generated.
$
Question: How do I fix it with Clang? Or am I missing something and Clang is right to reject the code?
Thanks to #HowardHinnant's comment, I managed to fix the problem. The problem became obvious in the preprocessor output: libstdc++ includes <exception> from <type_info> before it even declared std::type_info. That made Clang assume a new forward-declaration std::__exception_ptr::type_info. The solution is as simple as it is illegal:
namespace std { class type_info; }
#include <typeinfo>
#include <exception>
const char* get_name( const std::exception_ptr eptr )
{
return eptr.__cxa_exception_type()->name();
}
int main() {}
Seems like I should check if libstdc++ already has a bug report for that and, if not, create one.
UPDATE: Bug #56468 is now fixed for GCC 4.7.3+