cannot bind packed field 'st.ST::a' to 'int&' - c++

using different version of gcc, compile the following code
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
there is an error:
main.cpp:21:20: error: cannot bind packed field 'st.ST::a' to 'int&'
int & ref = st.a;
But
g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-4)
It runs all right.
If I add 'const' before the reference, and modify test function,(del t=10),like this.
It runs all right again.
const int & ref = st.a
***
int test(const int & t)
{
return 0;
}
Why?Why?Why?
#include <iostream>
using namespace std;
typedef struct
{
int a;
short b;
}__attribute__((packed)) ST;
int test(int & t)
{
t = 10;
return 0;
}
int main()
{
int a = 1;
ST st;
int & ref = st.a;
test(ref);
cout << ref << endl;
}
I have read
Passing reference of packed struct member to template. gcc bug?
and
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=36566
But they didn't say why it runs OK using g++ 4.4.6,but had an error using 4.8.5.
they didn't say why the 'const' can make the code goes right.
This is not a new feature, why gcc has two different results?

Related

gcc 4.8 failed to check type conversion in c++ template

I'm trying to update a c++ project's compiler from 4.8.4 to 7.5.0.
The codes can be well compiled with g++4.8.4. However, when I try to compile it with newer g++ 7.5.0. Lots of Werror=conversion errors are triggered.
Here is the demo code abstracted from my project:
// main.cc
template <typename T>
int Hello(T obj) {
float arg = 1.0;
// return obj.func(arg); // good, error detected for both g++ 4.8.4 and 7.5.0
return obj.func(arg) * 2; // failed to detect conversion error for 4.8.4, success for 7.5.0
}
class A {
public:
int func(int a) {
return a;
}
};
int main() {
A a;
Hello(a);
return 0;
}
build:
g++ main.cc -Werror=conversion
As commented above, in a c++ template function, g++4.8 failed to detect the type conversion error when it's in a expression. But it will sucess if it is alone.
I'm very curious about this.
My Question:
Is this a bug of g++4.8? Why does expression matter?

G++ command throws "expected '(' for function-style cast or type construction"

Function foo takes a vector of strings. It's defined as
bool foo(vector<string>& input);
When I call foo with:
foo(vector<string>{"abc"});
my compiler gives the following error:
error: expected '(' for function-style cast or type construction
and points to { as the start of the error. This compiles fine in Xcode but I get the error when running the following via command line with:
g++ -o -std=c++17 main.cpp
What is wrong with my g++ syntax?
G++ Version Information:
g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.3 (clang-1103.0.32.59)
Target: x86_64-apple-darwin19.4.0
Thread model: posix
Your command line specifies that the output file ("-o") should be called "-std=c++17" – it does not say anything about the language version, so you're compiling as C++03.
Remove the "-o" or add an actual file name.
Also, note that your "g++" is an alias for clang.
I took your code and tried to compile it. For me there was rather problem with trying to pass non const value to function. I changed function argument to const and it compiled and printed without any problem.
#include <iostream>
#include <vector>
bool foo(const std::vector<std::string>& v) {
for (auto& a : v) { std::cout << a << std::endl; }
return true;
}
int main()
{
bool result = foo(std::vector<std::string> {"1", "2", "3" });
// do something with result
return 0;
}
Compiled on: https://www.onlinegdb.com/online_c++_compiler
Function foo expects for an l-value.
You are generating an instance and passing it to the function. But lifetime of the object is not enough for the pass-by-reference call.
Here is an example below; instance of class A is immediately destructed.
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class A {
public:
A(int m): m(m) {
cerr << __func__ << endl;
}
~A() {
cerr << __func__ << endl;
}
int m;
};
int main() {
cerr << __func__ << endl;
A(5);
cerr << __func__ << endl;
return 0;
}
Outputs:
main
A
~A
main

After declaring a __m256 fail to access its members

When i tried to compile with icpc it shows "expression must have class type." Got confused about this. Please help.
int main()
{
__m256d temp;
temp.m256d_f64[0] = 1;
return 0;
}
I can reproduce this problem on my end. In the immintrin.h shipped with Intel Compiler, we have the following definition for __m256d:
typedef struct _MMINTRIN_TYPE(32) __m256d {
double m256d_f64[4];
} __m256d;
In the above definition, the struct name and alias are same which is confusing the current compiler. Intel Compiler doesn't seem to recognize the typedef name as a class which can proved with a smaller testcase:
$ cat test1.cc
typedef struct __m256d {
double m256d_f64[4];
} m256d;
int main()
{
__m256d temp;
temp.m256d_f64[0] = 1;
return 0;
}
$ icpc test1.cc –c
When I change the typedef and instantiate temp as shown below (use the typedefed name instead of struct name), ICC fails but GCC works:
$ cat test1.cc
typedef struct m256d {
double m256d_f64[4];
} __m256d;
int main()
{
__m256d temp;
temp.m256d_f64[0] = 1;
return 0;
}
$ icpc test1.cc -c
test1.cc(8): error: expression must have class type
temp.m256d_f64[0] = 1;
^
compilation aborted for test1.cc (code 2)
$ g++ test1.cc -c
I have reported this issue to compiler engineering team at Intel.

Clang static parameter to std::fill causing linker to fail

Using Clang++ (v3.8.0), the following code fails to link due to sSomeValue being an undefined reference.
#include <iostream>
struct MyClass
{
static constexpr int sSomeSize = 3;
static constexpr int sSomeValue = 10;
};
int foo()
{
int someArray[MyClass::sSomeSize] = {};
std::fill(std::begin(someArray), std::end(someArray), MyClass::sSomeValue);
return someArray[0];
}
int main()
{
std::cout << foo() << std::endl;
}
More precisely:
clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
/tmp/main-c8de0c.o: In function `foo()':
main.cpp:(.text+0x2): undefined reference to `MyClass::sSomeValue'
/tmp/main-c8de0c.o: In function `main':
main.cpp:(.text+0x16): undefined reference to `MyClass::sSomeValue'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
However, changing the definition of foo to
int foo()
{
int someArray[MyClass::sSomeSize] = {MyClass::sSomeValue, MyClass::sSomeValue, MyClass::sSomeValue};
return someArray[0];
}
does not exhibit the same linker error, even though sSomeValue is still being used.
What is going on here? Is the compiler doing some optimization around the std::fill call that I may not be aware of?
Note that g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out compiles, links, and outputs 10 as expected with v6.3.0.
The error is nothing to do with std::fill.
If you refer below documentation, it says: Reference variables can be declared constexpr (their initializers have to be reference constant expressions):
http://en.cppreference.com/w/cpp/language/constexpr
Slight modification of your code works fine. Just make the struct variables "const &" as said above.
#include <iostream>
struct MyClass
{
static constexpr int const& sSomeSize = 3;
static constexpr int const& sSomeValue = 10;
};
int foo()
{
int someArray[MyClass::sSomeSize] = {};
std::fill(std::begin(someArray), std::end(someArray), MyClass::sSomeValue);
return someArray[0];
}
int main()
{
std::cout << foo() << std::endl;
}
Also refer here for well explained article about constexpr and static
"Does static constexpr variable make sense?
Specially the last para in ticked answer.

template lambda sometimes doesn't compile

I would like to implement a generic visitor pattern for my trie data structure. Below is the extracted minimal fragment which makes trouble for compilers:
#include <functional>
struct Node {
size_t length;
};
template<typename N>
class C {
public:
size_t longest = 0;
std::function<void(const N )> f = [this](N node) {
if(node->length > this->longest) this->longest = node->length;
};
};
int main() {
Node n;
n.length = 5;
C<Node*> c;
c.f(&n);
}
It compiles with g++ (Ubuntu/Linaro 4.7.2-2ubuntu1), Ubuntu clang version 3.4-1ubuntu3 and with Apple LLVM version 5.0 (clang-500.2.79). icc (ICC) 14.0.2 says:
try_lambda_T.cc(15): error: "this" cannot be used inside the body of this lambda
if(node->length > this->longest) this->longest = node->length;
I found a similar post:
Class with non-static lambda member can't use default template paramers?
That story resulted in a bug report which was resolved in g++ 4.8.1:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54764
However, g++ (Ubuntu 4.8.2-19ubuntu1) results in:
internal compiler error: in tsubst_copy, at cp/pt.c:12125
std::function<void(const N )> f = [this](N node) {
^
Please submit a full bug report,
with preprocessed source if appropriate.
What can I do with it to have it compiled newest g++ (and, hopefully, icc)?
gcc-4.8.1 compiles the code if you don't use a non-static data member initializer to initialize f
template<typename N>
class C {
public:
C()
: f([this](N node) {
if(node->length > longest) longest = node->length;
})
{}
size_t longest = 0;
std::function<void(const N )> f;
};
Live demo
It even works if you prefer referring to longest as this->longest within the body of the lambda.