Reputation: 145
I'm looking for a way to produce a linker error when a function is declared but not defined in an exported class. Here is a simple example that illustrates the problem:
test.h:
#define DLLEXPORT __attribute__((__visibility__("default")))
class DLLEXPORT CLASS_A {
public:
CLASS_A();
~CLASS_A();
void withdefinition();
void nodefinition();
};
test.cpp:
#include "test.h"
CLASS_A::CLASS_A() {}
CLASS_A::~CLASS_A() {}
void CLASS_A::withdefinition() {}
Makefile:
CFLAGS = -Wall -Wextra -fvisibility=hidden -fvisibility-inlines-hidden -fPIC
LDFLAGS = -Wl,--no-undefined
top: test.so
test.o: test.cpp test.h Makefile
g++ $(CFLAGS) -c $< -o $@
nm -C test.o
test.so: test.o
g++ -shared $(CFLAGS) $(LDFLAGS) $< -o $@
nm -C test.so
The output that I see from "nm test.o" is the following:
nm -C test.o
0000000000000014 T withdefinition()
0000000000000000 T CLASS_A::CLASS_A()
0000000000000000 T CLASS_A::CLASS_A()
000000000000000a T CLASS_A::~CLASS_A()
000000000000000a T CLASS_A::~CLASS_A()
The function "withdefinition()" generates an external definition, while the function "nodefinition()" generates no symbol at all. In theory, if the compilation of test.cpp could generate an undefined symbol for "nodefinition" the subsequent link command would complain about the undefined symbol. Unfortunately, this only happens if "nodefinition()" is explicitly called in the code. This is an error that can commonly occur during refactoring and it would be helpful if it could be detected as early as possible - is there an easy way to do this automatically with the gcc toolchain?
Upvotes: 3
Views: 392
Reputation: 129344
Since the compiler doesn't actually KNOW which functions you are defining where, it's impossible for the compiler/linker to perform this task.
Note that the knowledge that there may be a function called nodefinition
is lost during the compilation phase, so this information is only retained if you actually USE the function somewhere.
You could possibly write some (or find someone else's already written) code-analysis tool using the clang analysing framework, if you have a strict "x.h" and "x.cpp" relationship, so no functionality declared in "x.h" is ever defined in another file than "x.cpp" (or files included by "x.cpp"). But if the implementation is allowed elsewhere, then it's only possible to detect when the function is actually needed by the linker.
Of course, code-review should also catch this sort of problem in most cases.
Upvotes: 0
Reputation: 119877
A (non-virtual) function declared but not defined produces no trace in the compiled code. This is by design. You cannot change it because such change will break absolutely everything.
Imagine every function, every class, every piece of data, every little nothing you have in the standard include
files that you don't use, don't care about and don't even know it exists leaving a symbol in your compiled code.
Upvotes: 1