Here is a code snippet:
class test {
public:
test(){
cout<<"I am in default constructor ";
}
static void func(const test &obj){
cout<<"I am in function ";
}
protected:
test( const test &o){
cout<<"I am in copy constructor ";
}
};
int main()
{
test::func(test());
}
The above code gives following error with g++ 3.4.6 (on Red Hat Linux) on compilation:
In function `int main()':
error: `test::test(const test&)' is protected
error: within this context
However if you compile with g++ 3.3.2 or g++ 4.4.3 or any other g++ version (on Red Hat Linux), it compiles successfully and gives following output:
I am in default constructor I am in function
In the above code, I have passed the temporary object (created by default constructor) to function func by reference. So why the compiler 3.4.6 is calling the copy constructor?
Most likely because older g++ versions (and I believe it stands for other compilers) were not fully c++ compliant and had more bugs then the current version. As you said, this works on a later version, therefore it is most likely fixed.
EDIT
by the way, have you tried changing compiler settings? Different optimization levels might have different bugs.
Related
The following example program uses a thread local template variable, and instantiates it using a type inside an anonymous namespace. This produces a linker error in gcc. In clang it actually compiles but does not run correctly.
#include <stdio.h>
template<typename T>
struct container {
container() { printf("construct: %p\n", this); }
~container() { printf("destruct: %p\n", this); }
};
template<typename T>
thread_local container<T> storage;
namespace {
struct bar {};
}
int main() {
auto& ref1 = storage<bar>;
auto& ref2 = storage<bar>;
}
On gcc this fails with a link error:
a.cpp:6:2: warning: ‘container<T>::~container() noexcept [with T = {anonymous}::bar]’ used but never defined
~container() { printf("destruct: %p\n", this); }
^
/tmp/ccgh0P15.o: In function `__tls_init':
a.cpp:(.text+0xa9): undefined reference to `container<(anonymous namespace)::bar>::~container()'
With clang the program compiles but produces very troubling output:
construct: 0x7fb8d1c003d0
construct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
destruct: 0x7fb8d1c003d0
Are there some rough edges surrounding thread_local/templated variables that I am running into here? I am unclear why this would ever produce a link error (the link error disappears if I remove thread_local). In the case of clang how could a double destroy of an object with static storage duration be anything but a compiler bug? In clang the issue disappears if I remove the anonymous namespace OR the thread_local specification, OR by removing one of the references in main().
Can anyone shed some light on this, I am mainly just curious if I am misunderstanding something. Thanks!
EDIT:
clang++ -v
Apple LLVM version 10.0.0 (clang-1000.11.45.5)
g++ -v
gcc version 7.3.0 (Ubuntu 7.3.0-27ubuntu1~18.04)
I have been playing around a bit with the [[noreturn]] attribute, which I'm trying to get a handle of and make use of (I understand [[noreturn]] is a C++11 standard attribute and __attribute__((noreturn)) is a GCC/Clang extension). As part of this, I enabled the Clang warning -Wmissing-noreturn.
> clang++ -v
Ubuntu clang version 3.7.1-svn253742-1~exp1 (branches/release_37) (based on LLVM 3.7.1)
Target: x86_64-pc-linux-gnu
Thread model: posix
foo.cpp:
enum bar
{
A = 1,
B,
C
};
void foo()
{
switch (bar())
{
case A:
case B:
case C:
default:
break;
}
}
int main()
{
foo();
return 0;
}
Then compile:
> clang++ foo.cpp -o foo -Wmissing-noreturn -std=c++14
foo.cpp:9:1: warning: function 'foo' could be declared with attribute 'noreturn'
[-Wmissing-noreturn]
{
^
1 warning generated.
It appears to me that it would return! What's going on here? Is this a compiler bug?
If you remove the "= 1" from A, then it compiles fine without a warning.
If I do make the foo() function [[noreturn]] void foo(), then it does crash with a segmentation fault.
Ok sorry for delete the last answer. It was wrong. Ok noreturn meann that the function never end. and the segementation fould is because bar is not a variable
Just to give a follow up to an old question: clang is correct, even if a little pedantic.
Indeed the attribute noreturn is applicable to your foo() function, since it doesn't return anything. The fact that clang of 2016 gets confused with the slight variation in the enumeration that is a problem.
But we should forgive clang for this pecadillo, for C++11 grammar is not what could be called very simple.
I was struggling with segmentation fault after returning from main in C++0x code compiled under GCC with MinGW, and have narrowed it to simple case:
class A {
public:
virtual ~A();
};
A::~A() {
}
const A a;
int main() {
return 0;
}
The reason is correlated with:
const qualifier before object, removing it stops seg fault,
Lack of constructor in class A - adding empty one stops seg fault.
Version of compialtor - newer TDM MinGW with gcc 4.8.1 does not build code causing seg fault.
Am I triggering some undefined behavior, or really compiler bug is reason of such behavior?
Affected compiler:
gcc --version
gcc.exe (tdm-1) 4.7.1
g++ --version
g++.exe (tdm-1) 4.7.1
ld --version
GNU ld (GNU Binutils) 2.22
This appears to be gcc bug 55893 that was fixed in 4.7.3. The attached testcase is very similar to yours:
struct foo
{
virtual ~foo () { }
};
int main ()
{
static const foo tmp;
}
The error occurs because gcc places the const object in read-only memory, because it is trivially constructible, without checking that the object has a non-trivial destructor. The destructor, being virtual, attempts to update the vtable pointer, leading to the segfault.
boost::mutex::scoped_lock is a handy RAII wrapper around locking a mutex. I use a similar technique for something else: a RAII wrapper around asking a data interface to detach from/re-attach to a serial device.
What I can't figure out, though, is why in the code below only my object mst — whose instantiation and destruction do have side effects — causes g++ to emit an "unused variable" warning error whereas l manages to remain silent.
Do you know? Can you tell me?
[generic#sentinel ~]$ cat test.cpp
#include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <iostream>
struct MyScopedThing;
struct MyWorkerObject {
void a() { std::cout << "a"; }
void b() { std::cout << "b"; }
boost::shared_ptr<MyScopedThing> getScopedThing();
};
struct MyScopedThing {
MyScopedThing(MyWorkerObject& w) : w(w) {
w.a();
}
~MyScopedThing() {
w.b();
}
MyWorkerObject& w;
};
boost::shared_ptr<MyScopedThing> MyWorkerObject::getScopedThing() {
return boost::shared_ptr<MyScopedThing>(new MyScopedThing(*this));
}
int main() {
boost::mutex m;
boost::mutex::scoped_lock l(m);
MyWorkerObject w;
const boost::shared_ptr<MyScopedThing>& mst = w.getScopedThing();
}
[generic#sentinel ~]$ g++ test.cpp -o test -lboost_thread -Wall
test.cpp: In function ‘int main()’:
test.cpp:33: warning: unused variable ‘mst’
[generic#sentinel ~]$ ./test
ab[generic#sentinel ~]$ g++ -v 2>&1 | grep version
gcc version 4.4.5 20110214 (Red Hat 4.4.5-6) (GCC)
Note that the question has changed since the other answers were written.
Likely the reason g++ doesn't warn in the current form is because mst is a reference, and constructing and destructing a reference has no side effects. It's true that here the reference is extending the lifetime of a temporary, which has effects in its constructor and destructor, but apparently g++ doesn't realise that makes a difference.
If my memory serves me right, g++ has the unfortunate habit of emitting unused variable errors differently depending on the optimization settings because the detection works at the optimizer level.
That is, the code is optimized in SSA form, and if the optimizer detects that a variable, after optimization, is unused, then it may emit a warning (I much prefer Clang analysis for this...).
Therefore it is probably a matter of detecting what the destructor does. I wonder if it takes a conservative approach whenever the definition of the destructor is offline, I would surmise this equates a function call then and that the this qualify as a use of the variable.
I suspect the reason is that your class has a trivial
destructor, and that g++ only warns about unused variables if
the destructor is trivial. Invoking a non-trivial destructor is a
"use".
I seem to be having trouble getting deprecated warnings to print out, for functions declared as virtual.
I'm using "g++ (GCC) 4.1.1 20061011 (Red Hat 4.1.1-30)."
My research shows that there might be problems in gcc 4.x regarding deprecating
pure virtual functions(i.e. class bueller{ virtual int cameron()=0;};),
but not... I'd guess you'd call them regular... virtual functions.
Just so we're on the same page...
foo.h
class Foo
{
void Foo_A() __attribute__((deprecated)); //non-virtual
virtual void Foo_B() __attribute__((deprecated)); //virtual
virtual void Foo_C() __attribute__((deprecated)) = 0; //pure virtual
};
Say I compiled this, an foo.cpp file and some main.cpp file using g++.
1)Anything that uses Foo_A() will indeed show a warning.
2)Anything that uses Foo_B() does NOT show a warning.
3)Anything that inherits Foo, implements Foo_C and then uses it does not show warning.
Number 1: it works, no problem.
Number 3: seems like a known bug/feature.. whatever..
There seems to be no explination for #2 however.
Perhaps it's tied up in #3, although nothing I've found makes mention of it.
Anyone know if I'm missing anything here regarding regular virtual class member functions that I want to deprecate?
BTW: -Wno-deprecate is NOT turned on in my makefiles.
Given this program:
struct Foo
{
virtual void Foo_B() __attribute__((deprecated)); //virtual
};
struct DerivedFoo : public Foo
{
};
int main()
{
DerivedFoo d;
d.Foo_B();
Foo &f = d;
f.Foo_B();
}
void Foo::Foo_B() {}
On CentOS 5.2 (gcc version 4.1.2 20080704 (Red Hat 4.1.2-44)), I get the same output that you describe:
g++ deprecate.cc -o deprecate
deprecate.cc: In function ‘int main()’:
deprecate.cc:14: warning: ‘Foo_B’ is deprecated (declared at deprecate.cc:3)
But, on Ubuntu 10.04.1 (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)), I get the output that you expect:
g++ deprecate.cc -o deprecate
deprecate.cc: In function ‘int main()’:
deprecate.cc:14: warning: ‘virtual void Foo::Foo_B()’ is deprecated (declared at deprecate.cc:3)
deprecate.cc:16: warning: ‘virtual void Foo::Foo_B()’ is deprecated (declared at deprecate.cc:3)
So, I'm guessing it was a compiler bug that got fixed.
Do you call Foo_B()/Foo_C() through a Foo pointer/reference, or a derived class? If you use a derived class it seems that you have to mark the methods deprecated in it as well, or you get the behaviour you describe.
Google shows an old discussion on this topic at a Debian list. But nothing more recent comes up on this topic. Try asking on the distribution's (RedHat's, in this case) lists.