g++ compiler not generating error/warning for undefined methods - c++

I have a class that has a declared method but not defined/used anywhere. I expected this piece of code to generate linking error but it did not. Looks like compiler is smart enough to remove dead code. Which default optimization is doing this? How can I explicitly disable it to generate the error?
#include <iostream>
using namespace std;
class Base{
public:
int x;
string name;
void set(int val){ x = val;};
int get(){ return x;}
void Init();
};
int main() {
Base base;
base.set(10);
cout << base.get() << endl;
return 0;
}
EDIT1: Here Init() function is not defined and neither used anywhere. So, I expected compiler to complain about this not defined. But don't see any error/warning.
Thanks in advance.

Generally the linker will only produce errors for undefined symbols that are used. As you never call Init there is no error.

Looks like compiler is smart enough to remove dead code.
The compiler is not even "smart" here. There is no code using a function so that function is not needed to produce an executable program.
The function is not even "ODR used" so technically the compiler would be wrong to require a definition.

Related

VS2017 version 15.8.3 successfully compiles inline method without returning a required value

I compiled the following code with VS2017 version 15.8.3. Its Warning Level is set to /W4. The code contains two simple getters, one of them GetM() is inline.
The GetM() inline getter does not have a return statement. However, VS2017 happily compiled the code without any warning or error.
The GetN() method will result in error C4716: 'Simple::GetN': must return a value if its return n; statement is commented out.
class Simple
{
int m = 0;
int n = 0;
public:
int GetM() const { /* No return here. */ }
int GetN() const;
};
int Simple::GetN() const
{
return n;
// No return here results in compiler error below.
// error C4716: 'Simple::GetN': must return a value
}
int main()
{
Simple obj;
}
Question: Should the compiler also generate error C4716 for the inline method GetM()?
A method fully defined inside the class definition is sort-of inlined. If it isn't expanded directly inline where it's used, it is compiled outside of the class body. This is the magic sauce that allows a method to see any members that were defined after it in the class.
If it is not used, maybe the compiler doesn't look at it deeply enough to spot the mistake. Maybe it doesn't look at it at all. Maybe it generates a warning and maybe not. That's up to the compiler. Visual Studio seems to have elected report a missing return statement as an error, but to not inspect an unused inline (or sort-of inlined) function.
By changing main to
int main()
{
Simple obj;
obj.GetM();
}
I can make Visual Studio produce error C4716 for gGetM as the function now must be compiled, inlined or not.
I can also
inline int Simple::GetN() const
{
}
to explicitly make GetN inline and "eliminate" the error.
This is all highly compiler, and possibly even compiler option, specific.

undefined reference to OOLUA::Proxy_class<T>::class_name

I am using OOLUA 2.0.0 and am receiving the error undefined reference to OOLUA::Proxy_class<TestClass>::class_name.
The code is:
class TestClass
{
int test_member;
public:
void setTestMember(int x) { test_member = x; }
int getTestMember() { return test_member; }
};
OOLUA_PROXY(TestClass)
OOLUA_MEM_FUNC(void, setTestMember, int)
OOLUA_MEM_FUNC(int, getTestMember)
OOLUA_PROXY_END
int main()
{
OOLUA::Script script;
script.register_class<TestClass>();
OOLUA::run_chunk(script, "local n = TestClass.new() \n n:setTestMember(42) \n print(\"test_member is: \" .. n:getTestMember()");
return 0;
}
The documentation here does not appear to say anything about this error. I'm not sure what class_name even is. Any help is appreciated.
By the way, I'm using GCC 4.9.2 to compile it.
So this is late but hopefully it will help if anyone else runs across a similar issue. Basically your example is missing an important but subtle part that will help explain why you got the link errors you got.
TestClass.hpp
class TestClass
{
int test_member;
public:
void setTestMember(int x) { test_member = x; }
int getTestMember() const { return test_member; }
static void aStaticMember() { }
};
OOLUA_PROXY(TestClass)
OOLUA_MEM_FUNC(void, setTestMember, int)
OOLUA_MEM_FUNC_CONST(int, getTestMember)
OOLUA_SFUNC(aStaticMember)
OOLUA_PROXY_END
TestClass.cpp
OOLUA_EXPORT_FUNCTIONS(TestClass
,setTestMember
)
OOLUA_EXPORT_FUNCTIONS_CONST(TestClass
,getTestMember
)
You must always put a OOLUA_EXPORT_FUNCTIONS block in the associated .cpp file so that the declarations from the OOLUA_PROXY block are defined. Even if you only have const member functions, you must still place an empty block e.g. OOLUA_EXPORT_FUNCTIONS(TestClass) in the .cpp file. In the event that your class only has static functions, you would be required to use a slightly different setup.
In summary:
OOLUA_PROXY declares a proxy class
OOLUA_EXPORT_FUNCTIONS blocks define the members of that class
Also, if your class has only static member functions exposed, you will need to include a OOLUA_EXPORT_NO_FUNCTIONS(TestClass) in the .cpp file. For every static member you must then use special syntax for registering the static functions with the Script.
using namespace OOLUA; //NOLINT(build/namespaces)
Script vm;
vm.register_class_static<TestClass>("aStaticMember",
&OOLUA::Proxy_class<TestClass>::aStaticMember);
The documentation is not very helpful in this matter, but if you reveiw the associated test source files, they in combination with the documentation are enough to get past most issues.
It would be better posting questions about the library to the mailing list oolua.org/mailinglist
Have a look at the documentation for the library, specifically exporting class functions[1]. Personally I would use the minimalist DSL for your functions instead of the expressive, this would then make your proxied functions like the following (however the get should really be a constant function):
OOLUA_MFUNC(setTestMember)
OOLUA_MFUNC(getTestMember)
[1] https://docs.oolua.org/_o_o_lua_proxying.html

Cannot create an instance of a class from another namespace?

Okay, so this is really werid. I've never encountered anything like this.
Part of my program (Fails to compile) contains three namespaces as following:
// namespaceA.h
namespace A {
enum Kind { jimmy, david };
}
// end of namespaceA.h
// namespaceB.h
#include "namespaceA.h"
namespace B {
class Tree {
public:
Tree *prev;
Tree *next;
Tree *down;
A::Kind kind;
Tree();
~Tree();
};
}
// end of namespaceB.h
// Implementation details of the class are placed in namespaceB.cc
// Constructor / Desctructor defined in the namespaceB.cc file!
// Something like this,
#include "namespaceB.h"
namespace B {
inline Tree::Tree() { ... }
inline Tree::~Tree() { ... }
}
// namespaceC.cc
#include "namespace.B"
namespace C {
void run() {
B::Tree *tree; // FINE
B::Tree tree; // Fail to compile!?
}
}
// end of namespaceC.cc
Now, g++ went along just fine but the linker ld complains:
"namespaceC.cc: undefined reference to `B::Tree::Tree()'
"namespaceC.cc: undefined reference to `B::Tree::~Tree()'
I have never ever encountered anything like this before... This just seems really weird, I don't even know any words/terms to describe this problem.
I would much appreciate any help.
Thanks,
namespaceC.cc: undefined reference to `B::Tree::Tree()'
namespaceC.cc: undefined reference to `B::Tree::~Tree()'
Those are not compiler errors, they are linker errors. The problem is that you declared the constructor and destructor, but never defined them. So the compiler finds the declarations and accepts them, but the linker cannot find the definitions to link the references to.
See this answer for what is a declaration and what is a definition and what they are good/needed for.
Your definitions of B::Tree::Tree() and B::Tree::~Tree() are declared inline. This means they are only available in that source file, not any others.
Either removing inline from the definitions, or moving the inline definitions into a header file included by all source files that need them, should fix the link errors.
You have to write the constructor and destructor for B::Tree somewhere either inline or in namespaceB.cc. By creating an instance of B, you are requiring the existence of the constructor and destructor.
The pointer compiles fine because all pointers are the same. It's just the semantics allowed for different object types differ.
It would have compiled find up until the point you tried to use it.
But to create an actual object, you need the actual definition.
To use definitions from another namespace, you either used scopes, or use using:
#include "namespace.B"
using namespace B;
namespace C {
void run() {
Tree *tree; // FINE
Tree tree; // Fail to compile!?
}
}
or:
#include "namespace.B"
namespace C {
void run() {
B::Tree *tree; // FINE
B::Tree tree; // Fail to compile!?
}
}
You declare the Tree constructor & destructor, but you don't show us where you define them (you just say you implement Tree in namespaceB.cc)
Assuming you have defined them, you must ensure you are including both namespaceC.o and namespaceB.o on your link line.
That's not a namespace problem, neither a compiler error. The compiler is happy, but linker fails to find the definition of B::Tree::Tree(). You need to supply the source file for implementation, or use -c flag to "just compile".
First, you declared constructor and destructor of class Tree yourself so compiler didn't provide default implementation - you need to implement them yourself! (Or just remove those declarations...).
It is not enough to include headers but you need to explicitly say that you're using namespaces from those headers:
In namespaceC.cc add using namespace B; after you include namespace.B or, even better, prepend types with a namespace qualifier:
B::Tree *tree;
B::Tree tree;
I tried the codes in Visual studio 2005. If I remove the "inline" in namespaceB.cc for the constructor and destructor, it can link without errors.
Then I found this post: G++ won't accept inline constructors in C++
it says that for inline functions you must have its definition in every file that calls the function. So it is recommended to put inline definition in header file.

From where does the compiler start reading

This is a small program :
#include <iostream>
using namespace std;
int main() {
f();
system("pause");
}
void f() {
static int x = 20 ;
class tester {
public :
tester() {
cout << x ;
}
} x1;
}
The error that i get here is :error C3861: 'f': identifier not found
If i place the function f above main I will get the desired output.
Why it is so ?
I was told that program execution begins at main. According to this the code should run in the first case also.
How does the compiler start reading the program?
The beginning of the compilation and the beginning of the execution of the program are two different things.
The execution starts from the main.
The compilation begins from the beginning of the file; the compiler don't "jump around" the file to find the needed pieces, but it reads the input in a linear fashion (I suspect that this related, among the other things, to the fact that the C++ grammar is really complicated).
When the compiler is at some point in parsing the file, it only knows what has been declared/defined up to that point1.
Because of this, function prototypes (and non-defining declarations in general) have been invented: the prototypes of all the functions defined in the file are put at the beginning of the file, typically after the #include directives or in a separated include file. The prototypes tell to the compiler that such functions will be defined later, and what is the function signature (i.e. name, parameters, return value).
The prototype is made as a normal function, but without the body, which is replaced by a semicolon2. For example, in your code you would write
void f();
before the main.
IIRC there are some relaxations to this rule that allow the compiler to "wait" for some declarations to make some template magic work, but this is not relevant here.
In a prototype is also common not to write the names of the parameters, leaving just their type (this can be done also in function definitions, but it doesn't make much sense there unless you have a formal parameter you don't use). Still, I prefer to leave the parameter names there as a form of documentation.
I was told that program execution begins at main.
And that's exactly the point.
The compiler starts from main, and then sees a call to f(), which it has not encountered so far (as it is defined afterwards), so it does not know what to do with it.
If you want to define f after main you can place a function prototype before, such as
#include <iostream>
using namespace std;
void f(); // <--- This tells the compiler that a function name f will be defined
int main() {
f();
system("pause");
}
void f() {
static int x = 20 ;
class tester {
public :
tester() {
cout << x ;
}
} x1;
}
To be able to call a function it must have been declared at some earlier point in the code. This is just a rule of the language designed to help compilers.
You can declare the function earlier with e.g.
void f();
...and then define it after main as you have done.
The compiler starts at the top and reads down to the bottom.
you'll need to have something like:
#include <iostream>
using namespace std;
void f();
int main() {
f();
system("pause");
}
void f() {
static int x = 20 ;
class tester {
public :
tester() {
cout << x ;
}
} x1;
}
No, the compiler needs to see at least a declaration of f() before it is used. A c(++) code file is a simple text file and must be read from begin to end by the compiler.
During the compilation process, when the compiler is evaluating main() it needs to know what f() is in advance to be able to generate the correct assembly code to call this function. That's why you need to put it before main() in this case.
As an alternative you can declare the prototype of f() before main() so the compiler knows it's a local function declared somewhere else on your file:
void f(); // prototype
int main()
{
// .. code ..
}
void f() // implementation of f()
{
// .. code ..
}

several definitions of the same class

Playing around with MSVC++ 2005, I noticed that if the same class is defined several times, the program still happily links, even at the highest warning level. I find it surprising, how comes this is not an error?
module_a.cpp:
#include <iostream>
struct Foo {
const char * Bar() { return "MODULE_A"; }
};
void TestA() { std::cout << "TestA: " << Foo().Bar() << std::endl; }
module_b.cpp:
#include <iostream>
struct Foo {
const char * Bar() { return "MODULE_B"; }
};
void TestB() { std::cout << "TestB: " << Foo().Bar() << std::endl; }
main.cpp:
void TestA();
void TestB();
int main() {
TestA();
TestB();
}
And the output is:
TestA: MODULE_A
TestB: MODULE_A
It is an error - the code breaks the C++ One Definition Rule. If you do that, the standard says you get undefined behaviour.
The code links, because if you had:
struct Foo {
const char * Bar() { return "MODULE_B"; }
};
in both modules there would NOT be a ODR violation - after all, this is basically what #including a header does. The violation comes because your definitions are different ( the other one contains the string "MODULE_A") but there is no way for the linker (which just looks at class/function names) to detect this.
The compiler might consider that the object is useless besides its use in Test#() function and hence inlines the whole thing. That way, the linker would never see that either class even existed ! Just an idea, though.
Or somehow, linking between TestA and class Foo[#] would be done inside compilation. There would be a conflict if linker was looking for class Foo (multiple definition), but the linker simply does not look for it !
Do you have linking errors if compiling in debug mode with no optimizations enabled ?