This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Function of templated class gets optimized out with -O3 if inlined in object

Hi,


I think we hit a compiler bug when compiling ( --abi=eabi -O3) a templated class with a function that is inlined in the same compilation unit.
Consider this minimal example:

template <unsigned int SIZE>

template 
class Tmpl {
public:
	// clear the complete log messge queue
	void fun();
};

template 
void Tmpl::fun() {
}

template class Tmpl<16>;

Tmpl<16> gErrors;

int init_fun() {
	gErrors.fun(); // commenting this line out makes it compile correctly
	return 0;
}

int i = init_fun();

When compiling (TI Code Generation Tools 7.4.14) this with the following command, the symbols for the Tmpl<16>::fun() function (_ZN4TmplILj16EE3funEv) are not generated:

cl6x.exe -c --abi=eabi -O3 myfile.cpp

I inspect the resulting myfile.obj file with the nm6x-tool.

As soon as I comment out the line mentioned above or compile with lower optimization settings (e.g. -O0), the generated object file contains the symbols for this function (like expected).

00000000 ? _ZN4TmplILj16EE3funEv
00000000 T _ZN4TmplILj16EE3funEv

Can you please confirm that this is a bug in the compiler?

Kind regards,

Roman

  • I'm sorry, I can't get this to compile with the TI compiler or with GCC. Are you sure you've copied the code verbatim? What options are you using? If you can get another compiler to accept it, which compiler and what command-line options?
  • I'll try again, something went wrong when pasting the code, sorry for that.


    template <unsigned int SIZE> class Tmpl { public: // clear the complete log messge queue void fun(); }; template <unsigned int SIZE> void Tmpl<SIZE>::fun() { } template class Tmpl<16>; Tmpl<16> gErrors; int init_fun() { gErrors.fun(); return 0; } int i = init_fun();

  • At level -O3, the optimizer completely inlined the call to Tmpl<SIZE>::fun() in init_fun, so it was able to eliminate the function entirely. This is not a bug. For EABI, the compiler may or may not generate a function body for a class member depending on whether it is used in that file, and may generate multiple copies in the various modules. At link time, the duplicates are removed. If Tmpl<16>::fun were used anywhere else in the program, that module would have a copy of the function, so it's not an error to remove it here.
  • The problem is, if I have the implementation of a templated function in a *.cpp file (and the declaration in a *.hpp-file), other translation units cannot instantiate the Tmpl<16>::fun function, which leads to linker errors ("undefined reference to ...").

    Citing the chapter on Templates (chapter 14) of the C++2003-Standard, paragraph 4:

    "A template name has linkage (3.5). A non-member function template can have internal linkage; any other
    template name shall have external linkage. [...]"

    Please correct me if I'm wrong, but I think that this means that the compiler may not eliminate the function entirely, as it "shall have external linkage" and it is explicitly instantiated in this very compilation unit (14.7.2).

    Anything that I'm missing here?

  • External linkage doesn't necessarily mean the symbol is required to be exported from this file; it means that this symbol refers to the same object/function everywhere in the program (with lots of caveats I won't list here). C++ requires that you have a declaration visible everywhere function Tmpl<16>::fun is called. If this function is used in a different module, there will by necessity be a complete definition, and the compiler will instantiate a fresh copy of the function body. If some module can't inline the function and thus needs an actual copy of the function body, it will always provide an actual copy, so there will be at least one actual copy at link time.

    Do you have a test case where you have another module that has the appropriate declaration, yet you still get an undefined reference at link time?
  • In my original problem, I had the declaration in a header-file, the definition in an *.cpp file. All functions of the templated class were in the object of the mentioned *.cpp file, except for one, which was inlined (as in the example I provided). Moving the implementation of this function to the header solved the problem.

    However, the original code (declaration in header; implementation and explicit instantiation in cpp) compiled fine using gcc (and also with the old coff abi), so I thought that this should also work using TI code generation tools with the new eabi binary format.

    I just assumed that it is not allowed to leave out a function which is explicitly instantiated in the cpp file, but apparently my assumption was not correct.

    Archaeologist said:


    Do you have a test case where you have another module that has the appropriate declaration, yet you still get an undefined reference at link time?

    I can construct such a test-case where the "appropriate declaration" is included via a header file. But it's really only the declaration, the definition (and explicit instantiation) is in the cpp file.