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.
Related
Is there a way to treat exception mismatch error as warning in clang?
source_file.cpp:12:18: error: exception specification of overriding function is more lax than base version
virtual void Func(){}
I am getting error with google mock for functions that specify exception specifier. Looking at https://github.com/google/googletest/pull/681 and other reported issue, not sure if this will get fixed in google mock, so at least for test code if possible I would like to disable this.
//clang 3.8.0
#include <iostream>
struct A
{
virtual void Func() throw() {}
};
struct B : public A
{
virtual void Func(){}
};
int main()
{
B b;
return 0;
}
Yes, using the -fms-extensions command line option.
MSVC only warns about this, so with clang MSVC compatibility mode, the code will compile, and the error will be replaced with an equivalent warning.
More about MSVC compatibility mode in clang documentation,
here.
While trying to compile some CUDA code using Intel Threading Building Blocks, I discovered what I think is a bug in nvcc. The following minimal example compiles fine using g++ 5.4:
class Sub;
class Other;
namespace internal {
class Base
{
private:
friend class ::Sub;
static void foo(::Sub& b);
static void foo(::Other& c);
};
}
class Sub : private internal::Base
{
public:
using internal::Base::foo;
};
void internal::Base::foo(Sub& b)
{
}
int main(int argc, char *argv[])
{
Sub *b;
b->foo(*b);
// Sub::foo(*b);
return 0;
}
But if I compile it with nvcc 8.0 combined with the same host compiler, using
nvcc -x cu -arch=sm_35 -c minimal.cc
I get the following interesting error:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:28:21: error: ‘internal::Base’ is an inaccessible base of ‘Sub’
A somewhat more descriptive error is obtained if Base is moved out of the internal namespace and into to global namespace:
../minimal.cc: In function ‘int main(int, char**)’:
../minimal.cc:6:12: error: ‘class Base Base::Base’ is inaccessible
class Base
^
../minimal.cc:32:5: error: within this context
b->foo(*b);
^
../minimal.cc:32:11: error: ‘Base’ is an inaccessible base of ‘Sub’
b->foo(*b);
Clearly, this seem to be due to the somewhat non-standard way of calling the static method using a pointer, and if that row is replaced by the one commented out, it compiles just fine.
Can someone confirm if this is valid C++ and thus a bug in nvcc, or invalid C++ that g++ somehow still happily accepts?
I dug some more into this, and saw that it indeed is a problem with one of the phases of the nvcc compilation. Using --save-temps, and checking out the resulting .cu.cpp.ii file, it turns out that this line
b->foo(*b);
gets substituted by the following
(b->internal::Base::foo(*b));
This does not compile with g++, since then the fact that foo is exported as public in Sub is lost. After all, this tries to explicitly access it from the base class where it is private. Using the other type of invocation (Sub::foo) does not result in any extra code being generated.
I conclude that this is an bug in nvcc. It is interesting that this substitution does not happen if the second overloaded void foo(::Other &c) is not declared in Base.
I have a simple program containing the following code:
namespace nam
{
struct S{};
void f(S *){}
}
void f(nam::S *){}
int main()
{
nam::f(nullptr);
nam::S s;
f(&s);
return 0;
}
I expect that this will compile fine because I am calling f the second time without specifying namespace nam. However, upon compiling the code, I get this error:
$ g++ main.cpp -std=c++11 -Wall -Wextra
main.cpp: In function ‘int main()’:
main.cpp:14:9: error: call of overloaded ‘f(nam::S*)’ is ambiguous
f(&s);
^
main.cpp:7:6: note: candidate: void f(nam::S*)
void f(nam::S *){}
^
main.cpp:4:10: note: candidate: void nam::f(nam::S*)
void f(S *){}
Compiler and version:
$ gcc --version
gcc (Debian 5.3.1-14) 5.3.1 20160409
After trying this with different compilers, similar errors are returned. This seems to be a defined part of C++. I can't find anywhere on the internet where it says that calling a function with a struct in namespace nam as a parameter effectively implies using namespace nam; and requires ::f to remove ambiguity. I have 2 questions about this:
Where is this defined in the C++ standard?
Is there a good reason for this behavior?
Personally I like to avoid using namespace x; and similar. I want the compiler to give me an error when I don't specify a namespace. This behavior stops the compiler from doing so, and this means my code is inconsistent in places, because I occasionally forget to specify the namespace when calling functions like f that are not declared globally anywhere.
Your implementation of f(nam::S*) is outside of the namespace of 'nam'
change:
void f(nam::S *){}
to:
void nam::f(nam::S *){}
(or just move the enclosing namespace bracket) and all should be fine.
if your call to f(&s) in the current namespace was intentional then you need to specify this by changing the function call to
::f(&s)
As was said in the comments, this is due to argument-dependent lookup. I guess now I'll have to figure out now if I want to always specify the namespace in my code where this would make it unnecessary, or never specify it.
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.
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.