Following code is a hypothetical code. This is a perfectly valid code under g++ (4.2.1). When compiled with Clang++ (4.2) it produces error as qualified reference to 'myclass' is a constructor name rather than a type wherever a constructor can be declared
class myclass
{
public:
myclass() { }
~myclass() {}
};
myclass::myclass* funct() {
return new myclass();
}
I could fix this by changing myclass::myclass* to myclass*. However I am not expected to change any code. Is there any commandline flags that I could provide in order to compile this code as is using Clang++ ?
No, there is no such flag : since this program is ill-formed, it should not compile.
If a compiler compiles it, then it is a compiler bug. This bug report looks like the one impacting your particular gcc version.
The code should be fixed to :
myclass* funct() {
return new myclass();
}
gcc 4.9.1 also rejects the code:
error: ‘myclass::myclass’ names the constructor, not the type
Unless the code base is happy with the rather old gcc 4.2, I see no alternative than to fix the code.
Related
I'm writing some code using pimpl idiom with unique_ptr. When I tried to use in-class initialization to set unique_ptr to nullptr by default, gcc gave a compile error, while clang and msvc both successfully compiled the code. And if I didn't use in-class initialization the error went away.
// A.h
#pragma once
#include <memory>
using namespace std;
class B;
class A
{
private:
////////////////////////
// here gives the error!
////////////////////////
unique_ptr<B> impl{nullptr}; // error only with gcc,
// ok with clang and msvc
unique_ptr<B> impl2; // ok with all three
public:
A();
~A();
};
// A.cpp
#include "A.h"
class B
{
private:
int b{5};
public:
B() = default;
~B() = default;
};
A::A() = default;
A::~A() = default;
// main.cpp
#include "A.h"
int main()
{
A a;
return 0;
}
When I compiled the above code, gcc complained "error: invalid application of ‘sizeof’ to incomplete type ‘B’". I've tried both gcc 8.3 and gcc 9.1 with no success. Is this a compiler bug? Thanks!
Edit:
I tried as #eerorika suggested. If the header and source files are merged into one single file, it can compile normally, but not separated.
Edit
Confirmed to be compiler bug and already fixed in gcc9.2.
The program, and the default member initialiser in particular, is well-formed. If a compiler refuses to compile, then it is a bug in the compiler as far as I can tell.
I can reproduce the problem with GCC 9.1 but not 9.2 nor trunk, so it appears to have been fixed. With older versions, you may need to give up using the default member initialiser as a workaround.
In VS2012, the below code doesn't compile, it says
error C4700: uninitialized local variable 'a' used on the line A<int> b(a);
I tested it in gcc4.4.7, it's fine.
I had thought something prevents the compiler to generate the default constructor, but it seems just an issue with VS2012. Why does it give this error, any explanation on how the compiler process the code?
template<typename T>
class A
{
public:
T* p;
};
int main()
{
A<int> a;
A<int> b(a);
}
I tested it in gcc4.4.7, it's fine.
In what sense do you think it's fine? You are never setting the value a.p so the code may compile, but it's still garbage data even with gcc.
By default, C4700 is a warning, not an error so you can get it to compile in the same broken way that gcc probably compiles it. You just have /WX set to treat warnings as errors, which good practice.
I am facing a compilation error with one gcc version (4.3.2), whereas the same code will be compiled without complaints with a newer version of gcc, e.g. 4.5.2.
The following example illustrates the problem:
class Base {
protected:
int member;
};
template<typename T>
class A : public Base {
};
template<typename T>
class C : public A<T> {
C() {
Base::member = 1;
}
};
int main() {
}
For 4.3.2 I am getting:
test.cpp: In constructor 'C<T>::C()':
test.cpp:4: error: object missing in reference to 'Base::member'
test.cpp:14: error: from this location
For 4.5.2 it compiles just fine.
If one compiler version accepts the code it cannot be completely wrong. My guess is that it conforms to the C++ standard, but the older compiler was lacking a proper implementation of the same.
What exactly is the problem?
Is there a portable way of writing that kind of code such that as much compilers as possible accept it?
This is definitely a bug in the earlier version of g++ but the solution is simple: Just add this-> to the expression, as this->Base::member = 1; which unconfuses the compiler.
I can easily achieve this in gcc using the used and noinline function attributes (see code below), but this doesn't work in clang even though it's supposed to support both of these function attributes.
A simplified example:
template<typename T>
struct Factory {
static __attribute__((used, noinline))
T createFoo() { return T(); }
};
int main() {
Factory<int> f; // instantiate and use Factory<int>
}
Compile the code in gcc and use nm to confirm that gcc correctly emitted the function:
nm --demangle test | grep createFoo
0000000000403185 W Factory<int>::createFoo()
The code compiles fine in clang, but it does not emit code for the static createFoo() function like it's supposed to.
How can I force clang to emit this static function which is never referenced?
This is definitely a bug in clang.
As the OP stated in a comment, the semantics of __attribute__((used)) is to treat the function as if it were actually referenced in the code, forcing it to emit code for the function, which clang is not doing in this case.
Furthermore, all class-member-functions have extern linkage as defined by C++. So when the class is instantiated, and the compiler (supporting gcc-style function attibutes) sees __attribute__((used)) for the member function, it should know immediately that an externally visible definition of that function should be emitted. gcc is doing this, bug clang is not.
A temporary workaround (for clang) is to explicitly reference the function somewhere in your code.
You should also file a clang bug report with llvm to get this issue fixed.
Note that derived uses C++11 uniform initialization syntax to call the base class constructor.
class base
{
protected:
base()
{}
};
class derived : public base
{
public:
derived()
: base{} // <-- Note the c++11 curly brace syntax
// using uniform initialization. Change the
// braces to () and it works.
{}
};
int main()
{
derived d1;
return 0;
}
g++4.6 compiles this, however g++4.7 does not:
$ g++-4.7 -std=c++11 -Wall -Wextra -pedantic curly.cpp -o curly
curly.cpp: In constructor ‘derived::derived()’:
curly.cpp:4:13: error: ‘base::base()’ is protected
curly.cpp:19:24: error: within this context
What's going on?
Update 1: It also compiles without warnings with clang++-3.1
Update 2: Looks like a compiler bug for sure. It's apparently fixed in GCC 4.7.3.
Paolo Carlini, a GCC/libstdc++ contributor, confirmed it is a bug/regression.
It is probably because in version 4.7 C11 explicit override control was added.
compiling this with icpc ( intel compiler tested with version 11.1 -> 12.1) gives:
-bash-3.2$ icpc -std=c++0x test.c
test.c(15): error: expected a declaration
{}
^
test.c(12): error: expected a "("
: base{} // <-- Note the c++11 curly brace syntax
^
compilation aborted for test.c (code 2)
edit: but then again, c++11 is not fully implemented yet in icpc either
http://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler/
same as with g++
http://gcc.gnu.org/gcc-4.7/cxx0x_status.html
which clearly states it's still experimental, so a bug is very likely.
I found this:
"The draft says that an initializer list initializing a reference is done not by direct binding, but by first constructing a temporary out of the element in the initializer list, and then binding the target reference to that temporary"
So it might be choking on the fact that the temporary created by base{} is being done through a protected constructor.