Imagine following code with CRTP and polymorphism:
template <typename Derived>
class CRTP {
public:
// in real code, the result of this cast is saved in another class
CRTP() { static_cast<Derived*>(this); }
};
class MyClass : public CRTP<MyClass> {
virtual void foo(){};
};
int main() {
MyClass m;
}
After reading Can you static_cast "this" to a derived class in a base class constructor then use the result later? and standard ([expr.static.cast]#12, [basic.life]#6, [class.cdtor]), I believe this is fine as long as the pointer and reference are not used aside from being saved to variable. However, UndefinedBehaviourSanitizer disagrees (see it on godbolt):
/app/example.cpp:4:14: runtime error: downcast of address 0x7ffdc5ba6df8 which does not point to an object of type 'MyClass'
0x7ffdc5ba6df8: note: object has invalid vptr
fd 7f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 83 00 04 1e ba 7f 00 00 80 8b 20 1e
^~~~~~~~~~~~~~~~~~~~~~~
invalid vptr
The error is gone if Derived
is not polymorphic.
Is it just a false positive from UBSan or is there anything in the standard that changes the situation in case of polymorphic classes?
For reference, my real code looks more like this: https://godbolt.org/z/f9sePhv73. I store a reference to the Derived
class in another class (not using in it constructor), and MyClass
also inherits a mixin that makes it virtual, so it's not too simple to get rid of vptr.