I have the following code:
typedef int __v8si __attribute__ ((__vector_size__ (32)));
class T
{
public:
__v8si v;
__attribute__((target("avx2")))
T(int p ):v(__extension__ __v8si{p,p,p,p,p,p,p,p}){}
__attribute__((target("avx2")))
T(__v8si p):v(p){}
__attribute__((target("avx2")))
T operator * ( T b ) const
{
return __builtin_ia32_pmulld256( v , b.v ) ;
}
};
void h(int *);
__attribute__((target("default")))
void h(int *)
{
}
__attribute__((target("avx2")))
void h(int *)
{
const T a(1);
const T b(2);
const T c (a * b);
}
int main()
{
return 0;
}
If I try to compile it,
I have the following error:
$ gcc test.cpp -std=c++11
test.cpp: In member function 'T T::operator*(T) const':
test.cpp:17:48: internal compiler error: in convert_move, at expr.c:315
return __builtin_ia32_pmulld256( v , b.v ) ;
^
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
I have tried to compile it with various gcc versions:
4.9.2, 5.3 and several other versions.
Have you any ideas why it happens, and how could I solve the problem?
gcc test.cpp -std=c++11 -mavx2 works.
gcc test.cpp -std=c++11 -O1 works.
but I want to compile the code with -O0
Update 1. I've filed a bug report. The report is available here:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77952
Related
I found a difference in behavior between gcc and clang when compiling BoringSSL, and was able to whittle it down to the following test case to illustrate:
typedef char *OPENSSL_STRING;
#if USE_TYPEDEF
#define constptr const OPENSSL_STRING
#else
#define constptr const char *
#endif
int
foo (const void **ap)
{
constptr a = (constptr) *ap;
return a != 0;
}
I tested four scenarios as follows:
sh$ g++ -c t2.cc -Wignored-qualifiers -DUSE_TYPEDEF
t2.cc: In function ‘int foo(const void**)’:
t2.cc:11:30: warning: type qualifiers ignored on cast result type [-Wignored-qualifiers]
11 | constptr a = (constptr) *ap;
| ^~
sh$ g++ -c t2.cc -Wignored-qualifiers
sh$ clang++ -c t2.cc -Wignored-qualifiers -DUSE_TYPEDEF
sh$ clang++ -c t2.cc -Wignored-qualifiers
sh$
Is this a bug in gcc -- or is there something more going on that I don't understand?
For reference: the warning is in BoringSSL's stack.h
Given const OPENSSL_STRING, const is qualified on the typedef OPENSSL_STRING itself, so the type would be char * const, i.e. const pointer to non-const char (note that it's not const char *). Gcc is just trying to tell you that as the cast result the const part is ignored. i.e. (char * const) *ap; has the same effect as (char *) *ap;.
Changing the type to int might be clearer.
const int i = (int) 0; // a weird conversion
const int i = (const int) 0; // same effect as above
Given the following code as test.cpp,
Building using clang++ -c test.cpp -o test.o -g; clang++ test.o -g -all_load, setting breakpoint at return a.getValue(); and attempting to p a.getValue() from lldb:
Running llvm 3.8.0 on unix - works perfectly
Running xcode or llvm 8.1.0 on OSX - I get the following error:
error: Couldn't lookup symbols:
__ZNK4Test7MyClassILi2ELi3EE8getValueEv
Two interesting facts:
If I remove the last template argument - all works well
If I build directly without going through the .o file (clang++ test.cpp) = all goes well
Anyone has a clue what is going on, and how can it be fixed?
namespace Test{
template<class T>
class BLA{
public:
T getBlaValue() const{return 3;}
};
template <int N1, int N2, template<class T>class Impl = BLA>
class MyClass {
private:
public:
__attribute__((used))
int getValue() const
{
return 3;
}
};
}
int main()
{
Test::MyClass<2, 3> a;
return a.getValue();
}
I have the following code:
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
void foo() const;
};
void A::foo() const {}
std::unique_ptr<A> foo2()
{
std::unique_ptr<A> pa(new A());
return pa;
}
void
foo()
{
const A& ra = *foo2();
ra.foo();
}
int
main()
{
foo();
return 0;
}
I am trying to use clang's scan-build:
scan-build g++ --std=c++11 unique_ptr.cpp
This program compiles and runs fine with g++.
I am using CentOS and clang3.8 and g++4.8.5.
Error Message:
error: no type named 'unique_ptr' in namespace 'std'
std::unique_ptr<A> foo2()
~~~~~^
You should use:
scan-build g++ -std=c++11 unique_ptr.cpp
Instead of:
scan-build g++ --std=c++11 unique_ptr.cpp
-std works (while --std doesn't) because scan-build checks specifically for the -std flag.
In clang/tools/scan-build/libexec/ccc-analyzer:
if ($Arg =~ /^-std=/) {
push #CompileOpts,$Arg;
next;
}
I've reduced a case to the code shown below here.
When compiling, this gives the following:
$ g++ -std=c++0x -O2 -Wall t.cpp
t.cpp: In function ‘int main()’:
t.cpp:20: warning: dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules
t.cpp:19: warning: dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules
/usr/lib/gcc/i686-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_tree.h:175: note: initialized from here
What is this warning telling me ? What can I do about it ?
#include <stdio.h>
#include <stdint.h>
struct TimeKey {
uint64_t time_stamp;
uint64_t msg_no;
TimeKey(uint64_t tstamp, uint64_t no) :
time_stamp(tstamp),
msg_no(no)
{}
bool operator < (const TimeKey &other) const
{
if (time_stamp == other.time_stamp) //line 19
return msg_no < other.msg_no; //line 20
else
return time_stamp < other.time_stamp;
}
};
template <typename T>
class TimeBuffer {
public:
uint64_t counter;
std::map<TimeKey, T> messages;
void AddMsg(uint64_t tstamp, T val) {
messages[TimeKey(tstamp, counter++)] = val;
}
};
int main(void)
{
TimeBuffer<int> messages;
messages.AddMsg(123456, 1);
}
Note, this is on RHEL 6.3, which comes with gcc 4.4.6
This is a known (and fixed) compiler bug, see this and this. You should update your toolchain.
I've got a very strange g++ warning when tried to compile following code:
#include <map>
#include <set>
class A {
public:
int x;
int y;
A(): x(0), y(0) {}
A(int xx, int yy): x(xx), y(yy) {}
bool operator< (const A &a) const {
return (x < a.x || (!(a.x < x) && y < a.y));
}
};
struct B {
std::set<A> data;
};
int
main()
{
std::map<int, B> m;
B b;
b.data.insert(A(1, 1));
b.data.insert(A(1, 2));
b.data.insert(A(2, 1));
m[1] = b;
return 0;
}
Output:
$ g++ -Wall -W -O3 t.cpp -o /tmp/t
t.cpp: In function ‘int main()’:
t.cpp:14: warning: dereferencing pointer ‘__x.52’ does break strict-aliasing rules
t.cpp:14: warning: dereferencing pointer ‘__x.52’ does break strict-aliasing rules
/usr/lib/gcc/i686-redhat-linux/4.4.2/../../../../include/c++/4.4.2/bits/stl_tree.h:525: note: initialized from here
It doesn't have any sence to me at all. How should I interpret it ? I don't see what's wrong with the code posted.
Forget to specify compiler details:
$ gcc --version
gcc (GCC) 4.4.2 20091027 (Red Hat 4.4.2-7)
gcc 4.4 has a bug where std::map breaks incorrectly warns about strict-aliasing rules.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39390
Your code is valid C++. Strict aliasing merely allows a subset of optimizations that are enabled by default when using -O3.
Your solution is to compile with -fno-strict-aliasing or a different version of gcc.
If you're curious about what strict aliasing is, that has been asked here.
Try to change this:
return (x < a.x || (!(a.x < x) && y < a.y));
into:
return (x < a.x || (a.x == x && y < a.y));
I also compiled this using your version and my version under g++ 3.4.2 and is all ok.
Which version of g++? g++ 4.3.2 compiles this without complaint.