Missing definition of a template virtual function

Srivastava, Sunil via cfe-commits cfe-commits at lists.llvm.org
Sun Jun 5 22:27:08 PDT 2016


Hi Richard,

Thanks for you analysis. I have some follow up questions though:

First, either of these two suggestions below should fix the bug, though it may be better to do both. Right ?

Then, approach (2) has a cost. It will prevent devirtualizations of calls which could get defined elsewhere.

While my example of https://llvm.org/bugs/show_bug.cgi?id=27895#c4   is good for demonstrating the bug, it is an unusual case. The usual case is that the template will be defined somewhere. So by suppressing devirtualization in this case we will be penalizing the usual cases to fix a bug in unusual cases.

The approach (1) is doable of course. It involves passing some kind of isFullObject flag few levels down in SemaOverload.cpp, and then prevent reset of OdrUse flag if isFullObject is true.

However I want to understand better what is going on here. Specifically, why virtual operators are treated different from virtual functions. In my example, if you replace the operator[] with a plain function doing the same thing, the function definition gets generated.

In your bugzilla comment 5, you perhaps alluded to this point:


> we model operator[] as weak_odr unnamed_addr, which would allow us to

> discard the symbol in the other translation unit if we can merge the

> function with something else, even though its address is exposed in

> the vtable

But what can the compiler do with user written operator[] that it can not do with a plain function ?

Beside, this bug is not just with operator[]. It is with every member operator.

Thanks
Sunil Srivastava
Sony Interactive Entertainment

Yes, this is a bug. We emit a direct call to TmplWithArray<bool,10>::operator[] so we're required to also emit a definition of it. I think the code that r227073 removed was really masking this bug rather than fixing it. It seems like there are two issues here:

 1) Sema should mark a virtual function as used if it sees an obviously-devirtualizable call to the function (where the base object has a known dynamic type)

 2) Clang CodeGen's devirtualization of obviously-devirtualizable calls should not devirtualize calls to linkonce_odr functions that it can't emit



----------------------------------------------
template < typename T, int N = 0 > class TmplWithArray {
public:
  virtual T& operator [] (int idx);
  T ar[N+1];
};
template <typename T, int N> T& TmplWithArray<T, N >::operator[](int idx) {
  return ar[idx];
}
class Wrapper {
  TmplWithArray<bool, 10> data;
  bool indexIt(int a);
};
bool Wrapper::indexIt(int a)
{
   return data[a];
}
int main(){}
----------------------------------------------

Starting from  r227073 it does not link (at any optimization level). The code
has a direct call to the operator[] function, but that function definition is
not generated.

Versions prior to r227073,
    -  at –O0 or –O1, generate the operator[] function and the direct call, and
    -  at –O2 do not generate the function, but inline it
Either way they link fine.

In this example the key-function for the generation of the vtable is the
operator[] function itself.

So the compiler can either generate both the vtable and the operator[]
function, or not generate either; they are both consistent states.

The call in data[a] is to a virtual function, and if the compiler left it as a
virtual call, it will link. There will be no ctor, no vtable, and no operator[]
function. Wrapper::indexIt will be dead code, but it will link.

But the compiler does devirtualization of the call and generates a direct call,
yet, beginning with r227073, it does not generate the operator[] function.
Hence the link failure.

Another interesting tidbit is that if the operator[] is replaced by a plain
function doing the same thing, along with the corresponding change in the
usage, something like:
    virtual T& getElt(int idx);
then the behavior is the same as pre r227073. Either getElt is defined or it
gets inlined.

BTW, this is not just an idle curiosity. This example was trimmed down from
a user bug report having a link failure.

Sunil Srivastava
Sony Interactive Entertainment

_______________________________________________
cfe-commits mailing list
cfe-commits at lists.llvm.org<mailto:cfe-commits at lists.llvm.org>
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160606/21df8d44/attachment-0001.html>


More information about the cfe-commits mailing list